How does Rust's `match` get compiled down by the compiler?
I am implementing a custom programming language and the goal is to make it a statically typed one. I initially was going to have some dynamic typing features (like runtime type introspection/reflection), but now I'm thinking maybe that can be avoided.
So I'm looking at Rust and on the surface it appears like you are checking the type at runtime (using the match pattern syntax):
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let msg = Message::ChangeColor(0, 160, 255);
match msg {
Message::Quit => {
println!("The Quit variant has no data to destructure.");
}
Message::Move { x, y } => {
println!("Move in the x direction {x} and in the y direction {y}");
}
Message::Write(text) => {
println!("Text message: {text}");
}
Message::ChangeColor(r, g, b) => {
println!("Change the color to red {r}, green {g}, and blue {b}",)
}
}
}
I saw somewhere else that the compiler sort of "expands" the syntactic sugar you give it into normalized more verbose code, so I'm partly wondering if that happens with match (and what an example of it might look like, expanded out).
Since rust is statically typed and not dynamically typed, this match must somehow work at compile time (I am imagining). So I am left imagining how that would look. All I can think of so far is that it would create variants of the parent function with one line of the match per function, sort of like this:
fn main_msg_quit() {
let msg = Message::ChangeColor(0, 160, 255);
println!("The Quit variant has no data to destructure.");
fn main_msg_move() {
let msg = Message::ChangeColor(0, 160, 255);
println!("Move in the x direction {x} and in the y direction {y}");
}
// ...
But that wouldn't work, as the more nested matchings you'd have would lead to a combinatorial explosion of function possibilities. So I'm not seeing how it can be done without runtime metadata.
Can you explain how this works at the compiler level in Rust?
- How does it check the type at compile time, and send the traffic to that branch at runtime (without checking the type at runtime)?