Test type_override fails even when correct solution is made in rust macros lesson

This code in tests/macros.rs:

#[test]
#[ignore]
fn type_override() {
    // The macro should always use std::collections::HashMap and ignore crate::std::collections::HashMap
    mod std {
        pub mod collections {
            pub struct HashMap;

            impl HashMap {
                #[allow(dead_code)]
                pub fn new() -> Self {
                    panic!(
                        "Do not allow users to override which HashMap is used"
                    );
                }

                #[allow(dead_code)]
                pub fn insert<K, V>(&mut self, _key: K, _val: V) {
                    panic!(
                        "Do not allow users to override which HashMap is used"
                    );
                }
            }
        }
    }

    let _empty: ::std::collections::HashMap<(), ()> = hashmap!();
    let _without_comma = hashmap!(1 => 2, 3 => 4);
    let _with_trailing = hashmap!(1 => 2, 3 => 4,);
}

incorrectly produces a compiler error when the correct std::collections::HashMap is used. I believe the intended purpose was to panic if the incorrect version was used, but it also breaks compiling the whole crate since rust throws a compiler error. Instead, we should use simple_trybuild::compile_fail to detect if the build succeeds. If it does, the hashmap macro was built incorrectly and we will fail the build. If it fails to compile, the usage is correctly using the std struct (presumably no one is going to build their own implementation of HashMap, though it would be technically permissible).

Interesting issue! (for some values of interesting :wink:)

There’s another solution, I think. First, in the fake std::collections module, add a conversion from the fake HashMap to a real one:

impl From<HashMap> for ::std::collections::HashMap<(), ()> {
    fn from(_value: HashMap) -> Self {
        Self::new()
    }
}

Then, when creating the empty HashMap in the test, convert it:

#[allow(clippy::useless_conversion)]
let _empty: ::std::collections::HashMap<(), ()> = hashmap!().into();
1 Like