Implementing Assert Macros in Rust
This challenge asks you to replicate the functionality of Rust's built-in assert! and assert_eq! macros. Understanding how these macros work provides insight into Rust's metaprogramming capabilities, error handling, and how to create useful developer tools within the language.
Problem Description
You are tasked with creating two macro definitions in Rust: my_assert! and my_assert_eq!.
my_assert!(expression):
- This macro should take a single boolean
expressionas input. - If the
expressionevaluates totrue, the macro should do nothing. - If the
expressionevaluates tofalse, the macro should panic and print a helpful error message indicating the failed assertion.
my_assert_eq!(left, right):
- This macro should take two expressions,
leftandright, as input. - It should compare
leftandrightfor equality. - If
leftis equal toright, the macro should do nothing. - If
leftis not equal toright, the macro should panic and print an error message showing both theleftandrightvalues, and ideally their debug representations.
Key Requirements:
- The macros must be defined using Rust's
macro_rules!syntax. - The error messages upon panic should be informative, similar to the standard library's assertions.
- The macros should be usable in the same way as the built-in
assert!andassert_eq!.
Expected Behavior:
When my_assert! or my_assert_eq! fails, the program should terminate with a panic, displaying a message that includes the source code location and the failed condition/values.
Edge Cases:
- Consider how to handle expressions that might have side effects (though for this challenge, we assume simple expressions).
- Ensure the error messages are clear even with complex types that implement
Debug.
Examples
Example 1: my_assert!
fn main() {
let x = 5;
my_assert!(x == 5); // This will not panic
// my_assert!(x == 10); // This would panic
}
- Input:
my_assert!(x == 5);wherexis 5. - Output: No output, program continues execution.
- Explanation: The expression
x == 5evaluates totrue, somy_assert!does nothing.
Example 2: my_assert_eq!
fn main() {
let a = 10;
let b = 10;
my_assert_eq!(a, b); // This will not panic
let c = 15;
// my_assert_eq!(a, c); // This would panic
}
- Input:
my_assert_eq!(a, b);whereais 10 andbis 10. - Output: No output, program continues execution.
- Explanation: The expressions
aandbare equal, somy_assert_eq!does nothing.
Example 3: Panic Behavior (my_assert!)
fn main() {
let condition = false;
my_assert!(condition); // This will panic
}
- Input:
my_assert!(condition);whereconditionisfalse. - Output: A panic message similar to:
thread 'main' panicked at 'assertion failed: condition', src/main.rs:4:5 - Explanation: The expression
conditionevaluates tofalse, causingmy_assert!to panic with the provided message indicating the failed expression.
Example 4: Panic Behavior (my_assert_eq!)
fn main() {
let val1 = "hello";
let val2 = "world";
my_assert_eq!(val1, val2); // This will panic
}
- Input:
my_assert_eq!(val1, val2);whereval1is"hello"andval2is"world". - Output: A panic message similar to:
thread 'main' panicked at 'assertion failed: `(left == right)`\n left: `"hello"`,\n right: `"world"`', src/main.rs:5:5 - Explanation: The expressions
val1andval2are not equal.my_assert_eq!panics, displaying theleftandrightvalues using theirDebugformat.
Constraints
- Your solution must be written in Rust.
- You must use
macro_rules!for macro definition. - The macros should not require any external crates.
- The macros should be able to handle any types that implement
PartialEqformy_assert_eq!andboolformy_assert!. - The panic messages should include the file name and line number where the macro was invoked.
Notes
- The
panic!macro is your primary tool for handling assertion failures. - Remember that macros in Rust operate on the abstract syntax tree (AST) before compilation.
- The
stringify!andformat_args!macros can be useful for constructing informative panic messages. - Pay attention to how you capture and pass the expressions to the macro. The
$expression:exprand$left:expr, $right:exprmetavariables are key. - The built-in
assert!andassert_eq!macros are good references for desired behavior and message formatting. You can find their source code in the Rust standard library documentation.