Replace the raw module with just hash_map
When I implemented Extend<Box<A>> for Map<A>, I thought:
can I implement Extend<(TypeId, Box<A>)> for RawMap<A>,
as HashMap<K, V> implements Extend<(K, V)>?
No, I responded, for insert is unsafe,
and a trait implementation cannot be marked unsafe.
Then said I, hang on, why is insert unsafe?
For by analogy with pointers, creating a dangling pointer is safe,
it’s only dereferencing it that’s unsafe;
so too here could insertion be safe and retrieval unsafe.
Then I realised: RawMap is actually completely safe, of itself;
the reason the unsafety is needed is AsMut<RawMap<A>> for Map<A>:
that retrieval is defined as safe, so insertion need be done delicately.
And so I consulted with myself and wondered:
Would it not be better to drop AsMut,
exposing rather an `unsafe fn as_raw_mut`?
For `AsRef<RawMap<A>>` and `Into<RawMap<A>>` may yet be safe,
yet this would take RawMap towards parity with HashMap.
And yet further went I,
descending into depths unplumbed these five years,
saying unto myself:
Wherefore RawMap<A> at all?
Why not rather HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>,
accessed freely and safely by reference or Into,
and unsafely as discussed in the previous stanza
(if I may call it such)?
Striving to understand the matter,
it was a wearisome effort,
and I could not.
I consulted with
143ee062680311ca9c2ed5b7089bb0d741bc17c0,
yet with the passage of nigh seven years it was not able to tell me
just why I had thought this might be a good idea.
For lo, those were the benighted ages before Rust 1.0.0,
though the glimmer of that bright dawn danced on the horizon
like the latter part of an arctic winter.
And so, casting away the trammels of history
I forged a new path.
For lo! had I not even then declared it
“not necessarily the final form”?
Casting RawMap away from me and clasping HashMap to my bosom,
I found the required diff in lib.rs
such a delicate thing,
so slight.
It was pleasing in my eyes, and so forthwith I decided:
hew down the unwanted abstraction,
and bind it with a band of iron and bronze,
that it may grow no more.
So need I not add more features to it,
mere shadows of the true HashMap underneath.
Oh fortunate day!
Three-hundred-odd lines removed,
(though more detailed comments offset this,
so that the end result is more like 223,)
and simplicity restored.
Well, except for this fly in the ointment:
std versus hashbrown.
Woe unto the person who calls a raw map std::collections::HashMap,
for when another comes and enables hashbrown,
the first shall crumble into nothingness and errors most distressing.
The mitigation of this is `pub type RawMap<A>`,
augmented by the very truth that,
few using this feature,
few may stumble!
Yet there are difference betwixt the twain,
seen in my cfg branching on VacantEntry and OccupiedEntry,
and this *is* a very mild violation of the principle of strictly additive features.
There ’tis: the tale of an abstraction unravelled.
Unravelled? Feels more like “not ravelled” rather than undoing ravelling.
Deravelled? Disravelled?
I shall but brand the abstraction a dead princess, as it were,
and this my pavane pour un infante défunte.
And if you, dear reader—
if reader there be of this screed that has grown rather longer than originally anticipated but also probably more entertaining if you don’t mind this sort of thing or share a similar sense of humour to me—
have aught to opine on the matter,
You know my email address.