how rust compiles

the rust compilation model has surprising effects

introduction to me

Noratrieb (she/her)
contributing to the compiler since 2021

behind cargo build

cargo vs rustc


                    $ cargo build
                
cargo
rustc (clap)
rustc (tokio)
rustc (tracing)
rustc (yourcrate)

so you want to compile a crate

so you want to compile a crate

source code:


              #[no_mangle]
              pub fn add(a: u8, b: u8) -> u8 {
                a.wrapping_add(b)
              }
            

so you want to compile a crate

MIR

codegen units


fn main() {}
          
              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
              flowchart LR
                mainmir["main (MIR)"]

                subgraph mycgu1[my CGU 1]
                  mainll["main (LLVM IR)"]
                end

                mycgu1 --> mycgu1.rcgu.o

                mainmir --> mainll

                mycgu1.rcgu.o --> my_binary
                std["std (and others)"] --> my_binary
            

codegen units (but more)


fn main() {}
fn foo1() {}
fn foo2() {}
          
              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
              flowchart LR
                mainmir["main (MIR)"]
                foo1mir["foo1 (MIR)"]
                foo2mir["foo2 (MIR)"]

                subgraph mycgu1[my CGU 1]
                  mainll["main (LLVM IR)"]
                end
                subgraph mycgu2[my CGU 2]
                  foo1ll["foo1 (LLVM IR)"]
                  foo2ll["foo2 (LLVM IR)"]
                end
                
                mycgu1 --> mycgu1.rcgu.o
                mycgu2 --> mycgu2.rcgu.o

                mainmir --> mainll
                foo1mir --> foo1ll
                foo2mir --> foo2ll

                mycgu1.rcgu.o --> my_binary
                mycgu2.rcgu.o --> my_binary
                std["std (and others)"] --> my_binary
            

codegen units (cross-crate)


fn add() {}
          

fn main() { math::add() }
          
              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
              flowchart LR
                subgraph crate math
                  addmir["add (MIR)"]

                  subgraph mathcgu1[math CGU 1]
                    addll["add (LLVM IR)"]
                  end

                  addmir --> addll

                  mathcgu1 --> mathcgu1.rcgu.o

                  mathcgu1.rcgu.o --> libmath.rlib
                end

                subgraph my crate
                  mainmir["main (MIR)"]

                  subgraph mycgu1[my CGU 1]
                    mainll["main (LLVM IR)"]
                  end

                  mycgu1 --> mycgu1.rcgu.o

                  mainmir --> mainll

                  mycgu1.rcgu.o --> my_binary
                  libmath.rlib --> my_binary
                  std["std (and others)"] --> my_binary
                end
            

instantiating generics


            fn add<T: Add>(a: T, b: T) -> T::Output { a + b }
            fn main() {
              add(0_u16, 0_u16);
              add(0_u32, 0_u32);
            }
          
              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
              flowchart LR
                addmir["add (MIR)"]
                useitmir["main (MIR)"]

                subgraph mycgu1[my CGU 1]
                  addu16ll["add_u16 (LLVM IR)"]
                  addu32ll["add_u32 (LLVM IR)"]
                  useitll["main (LLVM IR)"]
                end

                mycgu1 --> mycgu1.rcgu.o

                addmir -->|instantiate with T=u16| addu16ll
                addmir -->|instantiate with T=u32| addu32ll
                useitmir --> useitll

                mycgu1.rcgu.o --> my_binary
                std["std (and others)"] --> my_binary
            

generics (cross-crate)


            pub fn add<T: Add>(a: T, b: T) -> T::Output {
              a + b
            }
          

            fn main() {
              add(0_u16, 0_u16);
              add(0_u32, 0_u32);
            }
          
              %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'fontSize': '25px' }}}%%
              flowchart LR
                subgraph crate math
                  addmir["add (MIR)"]
                end

                subgraph my crate
                  mainmir["main (MIR)"]
                end

                subgraph my crate
                  subgraph mycgu1[my CGU 1]
                    addu16ll["add_u16 (LLVM IR)"]
                    addu32ll["add_u32 (LLVM IR)"]
                    mainll["main (LLVM IR)"]
                  end

                  mainmir --> mainll
                  addmir --> addu16ll
                  addmir --> addu32ll
                  mycgu1 --> mycgu1.rcgu.o
                  mycgu1.rcgu.o --> my_binary
                  std["std (and others)"] --> my_binary
                end