Why does the Drop trait take a mutable reference?

I don't have much of an opinion on how Drop should work, but the last few messages feel like they rhyme with a discussion a couple months ago, over on the users board, about how there's no good way to remove the maximal element of a map with non-Copy keys, particularly what I said about a hole in the type system:

In an unchecked language, you could define a BTreeMap::remove that accepted a key reference -- or maybe I should call it a pointer -- pointing into the map from which the key was to be removed. There is no obstacle to making the internals of the map handle this case correctly. The documentation would say that if you do this, the key reference is invalidated by the operation, and it would be the programmer's responsibility to not use that reference again afterward.

But in safe Rust there is no way to define a function that takes a mutable reference and one or more immutable references, and if the immutable references refer to the same object as the mutable reference, that's fine, but those references are consumed by the operation. References are Copy and you can't declare a function that moves references out of its arguments.

I'm not sure what you mean. If it was sound to arbitrarily read out of a MaybeUninit<T> just because the value is initialized, then MaybeUninit::new would be unsound because you could create infinitely many copies of Drop types.

For what it's worth, I think assume_init_read should be split into two functions, an assume_init_copy which requires the type to be Copy and an assume_init_move which takes an &mut MaybeUninit<T> reference. The safety conditions would then be much simpler (i.e. all that would be necessary to use them safely would be that the memory actually is initialised – the latter would be considered to deinitialise the memory).

If the &T is truly read-only, then it should be sound AFAICT. My concern would be something like transposing &MaybeUninit<Cell<T>> and &Cell<MaybeUninit<T>>. That cast itself is sound, but exposing the result to safe code is even more dubious than &Cell<T> -> &MaybeUninit<Cell<T>>. Exposing both casts to arbitrary safe code is of course unsound, so the question would be whether one or both is unsound, or whether this is “independent of Rust’s axioms” or whatever.