Hone logo
Hone
Problems

Macro Magic: Building a Custom Assert Macro in Rust

Macros in Rust offer powerful metaprogramming capabilities, allowing you to generate code at compile time. This challenge will guide you through creating a function-like macro that behaves similarly to Rust's built-in assert_eq! macro, but with a custom message. This exercise will deepen your understanding of macro syntax, expression parsing, and code generation.

Problem Description

Your task is to create a Rust macro named my_assert_eq that takes two expressions as arguments. This macro should:

  1. Compare the two expressions for equality.
  2. If the expressions are not equal, it should panic with a formatted error message that includes the values of both expressions and the source code representation of the expressions themselves.
  3. If the expressions are equal, it should do nothing (just like assert_eq!).

This is useful for writing more informative assertions in your tests or debugging code, especially when the default error messages might not be sufficient.

Examples

Example 1:

// Inside a function or test
let x = 5;
let y = 5;
my_assert_eq!(x, y);

Output: (No output or panic, as x and y are equal)

Explanation: The macro compares x and y. Since they are equal, the macro completes successfully without any side effects.

Example 2:

// Inside a function or test
let a = 10;
let b = 20;
my_assert_eq!(a, b);

Expected Panic Output:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `10`,
 right: `20`'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Explanation: The macro compares a and b. Since they are not equal, it panics. The panic message includes the values of a (10) and b (20), along with the original expression comparison (left == right).

Example 3:

// Inside a function or test
struct Point { x: i32, y: i32 }
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 1, y: 3 };
my_assert_eq!(p1.y, p2.y); // This will panic

Expected Panic Output:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `2`,
 right: `3`'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Explanation: The macro compares the y fields of p1 and p2. As they are not equal, it panics with the values of p1.y (2) and p2.y (3).

Constraints

  • The macro must be a function-like macro, meaning it should be invoked using macro_name!(...).
  • The macro should accept exactly two arguments, both of which are Rust expressions.
  • The expressions passed to the macro must implement the PartialEq trait.
  • The macro should not require any specific traits beyond PartialEq for the types of the expressions being compared.
  • The generated code should leverage standard Rust panic mechanisms.

Notes

  • Recall how to define macros in Rust using macro_rules!.
  • Consider how to capture the string representations of the input expressions for display in the panic message.
  • Think about how to ensure the macro correctly handles different types of expressions, as long as they are comparable with ==.
  • The panic! macro is your friend for generating the error message. You can use string formatting within panic!.
  • The stringify! macro can be helpful in capturing the source code of an expression.
Loading editor...
rust