maplit icon indicating copy to clipboard operation
maplit copied to clipboard

Strict versions of the macros

Open Xion opened this issue 8 years ago • 3 comments

By "strict" I mean ones that panic on duplicate keys/items.

The rationale has to do mostly with hashmaps that serve as "registries" of some sort. In my project, for example, there is a hashmap! of supported remote services where each one should have a unique textual identifier. As their number grows, I've became somewhat concerned about accidental name clashes.

Something like hashmap_strict! would helpful in catching these kinds of problems. It doesn't have to be fancy at all; a simple hashmap.insert(k, v).and_then(|_| panic!("duplicate hashmap key: {:?}")); would be sufficient (and the Debug requirement for keys is in line with panicking functions in stdlib, e.g. expect).

Xion avatar Dec 25 '17 20:12 Xion

That's interesting but I would prefer to do this in a way that didn't duplicate all the macros?

bluss avatar Jan 24 '18 21:01 bluss

In my vec_map macro (for VecMap) that was modelled after the maplit macros, I got bitten by this. I ended up adding an assertion:


macro_rules! vec_map {
	(@single $($x:tt)*) => (());
	(@count $($rest:expr),*) => (<[()]>::len(&[$(vec_map!(@single $rest)),*]));

	($($key:expr => $value:expr,)+) => { vec_map!($($key => $value),+) };
	($($key:expr => $value:expr),*) => {
		{
			let _cap = vec_map!(@count $($key),*);
			let mut _map = ::vec_map::VecMap::with_capacity(_cap);
			$(
				assert!(_map.insert($key, $value).is_none()); // panic if map literal contains duplicate keys
			)*
			_map
		}
	};
}

Then it looks like this:

assertion failed: _map.insert(key, value).is_none() With the line where the macro is called.

I think it'd make sense if the maplit macros also did this by default.

Boscop avatar Sep 15 '18 18:09 Boscop

I just ran into this as well in a use case like this:

         let entrysets = maplit::hashmap!{
            "straightline" => maplit::hashmap!{
                "A" => SynthEntry(1,1,1, (0, [(0,0),(0,0),(0,0)])),
                "B" => SynthEntry(2,2,1, (1, [(1, 1),(0,0), (0,0)])),
                "B" => SynthEntry(3,3,1, (2, [(1,1),(2,1), (0,0)])),
                "B" => SynthEntry(4,4,1, (3, [(2,1),(3,1),(0,0)])),
            }
        };

(Context doesn't matter here). My expectation was that I'd get a compile-time error here because I used string literals as keys.

problame avatar Jan 28 '21 11:01 problame