Description
In the current version of exercises/02_functions/functions5.rs, the goal is to fix the function body by converting a statement into an expression without changing the function signature.
While the exercise successfully teaches the difference between expressions and statements, I discovered a potential Integer Overflow risk during my testing, which might be a valuable "teachable moment" for new Rustaceans.
The Observation
The current implementation uses i32 for both the input and the return type:
// TODO: Fix the function body without changing the signature.
fn square(num: i32) -> i32 {
num * num
}
As suggested in intro1.rs, I tried to "keep trying things" even after figuring out the solution. When I changed the input in main to a boundary value, the program panicked.
Reproducible Panic Case
If we test the function with the square root of i32::MAX (approximately 46340):
fn main() {
let answer = square(46341);
println!("The square is {answer}");
}
Runtime Error:
thread 'main' panicked at src/main.rs:3:5:
attempt to multiply with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
A More Robust (but restricted) Approach
If we were allowed to change the signature (which this exercise specifically forbids), a safer real-world implementation would be:
fn square(num: i32) -> i64 {
(num as i64) * (num as i64)
}
Using the maximum i32 value (2147483647) with this logic yields the correct result (4611686014132420609) without panicking.
Proposal
I understand that Rustlings exercises are designed to be "small exercises to get you used to reading and writing Rust code" and often focus on one specific concept at a time. However, considering Rust's focus on Safety, it might be beneficial to:
- Add a comment in functions5.rs mentioning that while this implementation works for small values like 3, it does not handle Integer Overflow.
- Or, simply acknowledge this as a known simplification for educational purposes.
I believe this would help learners develop the "security-first" mindset that Rust is known for.
I'm happy to provide a PR if this is something the maintainers would like to include as a comment in the exercise!
Description
In the current version of exercises/02_functions/functions5.rs, the goal is to fix the function body by converting a statement into an expression without changing the function signature.
While the exercise successfully teaches the difference between expressions and statements, I discovered a potential Integer Overflow risk during my testing, which might be a valuable "teachable moment" for new Rustaceans.
The Observation
The current implementation uses i32 for both the input and the return type:
As suggested in intro1.rs, I tried to "keep trying things" even after figuring out the solution. When I changed the input in main to a boundary value, the program panicked.
Reproducible Panic Case
If we test the function with the square root of i32::MAX (approximately 46340):
Runtime Error:
A More Robust (but restricted) Approach
If we were allowed to change the signature (which this exercise specifically forbids), a safer real-world implementation would be:
Using the maximum i32 value (2147483647) with this logic yields the correct result (4611686014132420609) without panicking.
Proposal
I understand that Rustlings exercises are designed to be "small exercises to get you used to reading and writing Rust code" and often focus on one specific concept at a time. However, considering Rust's focus on Safety, it might be beneficial to:
I believe this would help learners develop the "security-first" mindset that Rust is known for.
I'm happy to provide a PR if this is something the maintainers would like to include as a comment in the exercise!