Challenge 9
Spot the Bug
Identify why the code fails to compile and suggest a way to fix it.
trait MathOperation { fn operate(&self, x: i32, y: i32) -> i32; } struct Addition; impl MathOperation for Addition { fn operate(&self, x: i32, y: i32) -> i32 { x + y } } fn perform_operation(op: &MathOperation, x: i32, y: i32) -> i32 { op.operate(x, y) } fn main() { let add_op = Addition; let result = perform_operation(&add_op, 10, 5); println!("Addition result: {}", result); }
Solution
Click to Show/Hide Solution
The Bug: Compiler error!
The bug lies in the perform_operation
function and how it interacts with the MathOperation
trait.
Solution:
The function takes a reference (&) to the MathOperation trait. This creates a reference to the trait definition itself, not a reference to a specific type that implements the trait. The compiler requires us to use the dyn
keyword to explicitly declare a dynamically sized trait object.
Why dyn
is Necessary:
Specifying dyn
is necessary because trait objects are dynamically sized. They can hold a reference to any type that implements the MathOperation trait. The actual type is only determined at runtime. Without dyn, the compiler cannot determine the size of the data in the trait object, making it impossible to call methods through it.
trait MathOperation { fn operate(&self, x: i32, y: i32) -> i32; } struct Addition; impl MathOperation for Addition { fn operate(&self, x: i32, y: i32) -> i32 { x + y } } fn main() { let add_op = Addition; let result = perform_operation(&add_op, 10, 5); println!("Addition result: {}", result); } fn perform_operation(op: &dyn MathOperation, x: i32, y: i32) -> i32 { op.operate(x, y) }