Hone logo
Hone
Problems

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 expression as input.
  • If the expression evaluates to true, the macro should do nothing.
  • If the expression evaluates to false, 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, left and right, as input.
  • It should compare left and right for equality.
  • If left is equal to right, the macro should do nothing.
  • If left is not equal to right, the macro should panic and print an error message showing both the left and right values, 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! and assert_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); where x is 5.
  • Output: No output, program continues execution.
  • Explanation: The expression x == 5 evaluates to true, so my_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); where a is 10 and b is 10.
  • Output: No output, program continues execution.
  • Explanation: The expressions a and b are equal, so my_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); where condition is false.
  • Output: A panic message similar to:
    thread 'main' panicked at 'assertion failed: condition', src/main.rs:4:5
    
  • Explanation: The expression condition evaluates to false, causing my_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); where val1 is "hello" and val2 is "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 val1 and val2 are not equal. my_assert_eq! panics, displaying the left and right values using their Debug format.

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 PartialEq for my_assert_eq! and bool for my_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! and format_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:expr and $left:expr, $right:expr metavariables are key.
  • The built-in assert! and assert_eq! macros are good references for desired behavior and message formatting. You can find their source code in the Rust standard library documentation.
Loading editor...
rust