What are the validity requirements of wide pointers/references with dyn Trait tail? · Issue #516 · rust-lang/unsafe-code-guidelines (original) (raw)

This is the last remaining part of #166, now that #510 has been resolved.
Note that the safety invariant for both of these is pretty much set already since casts from *const dyn Trait to *const dyn Supertrait are safe -- that means the vtable pointer must be valid for the given trait, even on raw pointers.

For the validity of the metadata in references, there seems to be general consensus that it is the same as the safety invariant: the vtable must be a vtable for the right trait (and an arbitrary type).

So the open question is what to do with the validity of metadata in raw pointers. The two contradicting goals pursued by different people here are:

This was discussed in Zulip somewhat recently. My proposal was to take a maximally liberal validity invariant, and allow any vtable pointer, but several people had concerns that it would be confusing to allow allow a null (or general, unsafe) vtable to exist but then make it UB to cast that pointer or use it as a dyn receiver, even though that operation is safe. One possible compromise was to explicitly allow only null and then make that actually safe by adding checks on casts and dyn calls -- but that would go against the idea of using raw pointers in cases where performance matters and safe code has too many checks.

It is also worth noting that t-lang has an FCP that touches on this question in rust-lang/rust#101336, where they recommend that the validity invariant should require vtable pointers to be word-aligned and non-null but nothing else. This would be half-way between "maximally liberal" and the expected invariant for &dyn Trait; it raises the question whether &dyn Trait should be made to have the same validity invariant just to avoid potential confusion from the difference.