Hi friends,
I'm a bit of a Rust noob here, and I'm taking a dive into automatic dereferencing rules. While that was happening, I noticed that the assert_eq!
macro doesn't do what I'd expect.
Here, I have a function that takes two references and compares them for equality:
let a = [1, 2];
let b = [1, 2];
fn assert(c: &[i32; 2], d: &[i32; 2]) {
assert_eq!(c, d);
}
assert(&&&&a, &&b);
This works how I would expect it to based on the rules I am reading. However, this fails:
assert_eq!(&&&&a, &&b);
So, I took a look at the macro and I think I understand why, but I'm curious if it's by design. The relevant section (mod.rs - source):
macro_rules! assert_eq {
($left:expr, $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
// The reborrows below are intentional. Without them, the stack slot for the
// borrow is initialized even before the values are compared, leading to a
// noticeable slow down.
panic!(r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`"#, &*left_val, &*right_val)
}
}
}
});
}
Would it be desirable to have assert_eq!
deref, and is something like this just plain wrong?
// Same functionality but derefs bc of the function call
macro_rules! my_assert_eq {
($left:expr, $right:expr) => ({
fn test<T: std::cmp::PartialEq + std::fmt::Debug>(left_val: &T, right_val: &T) {
if !(*left_val == *right_val) {
panic!(r#"assertion failed: `(left == right)` left: `{:?}`, right: `{:?}`"#, &*left_val, &*right_val)
}
}
test($left, $right);
});
}
With this example macro, I'm able to produce the desired functionality:
let a = [1, 2];
let b = [1, 2];
fn assert(c: &[i32; 2], d: &[i32; 2]) {
assert_eq!(c, d);
}
my_assert_eq!(&&&&a, &&b);