@@ -959,8 +959,35 @@ impl<'a, 'tcx> CastCheck<'tcx> {
959959 // dyn Auto -> dyn Auto'? ok.
960960 ( None , None ) => Ok ( CastKind :: PtrPtrCast ) ,
961961
962- // dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
963- // FIXME: allow this
962+ // dyn Trait -> dyn Auto? not ok (for now).
963+ //
964+ // Although dropping the principal is already allowed for unsizing coercions
965+ // (e.g. `*const (dyn Trait + Auto)` to `*const dyn Auto`), dropping it is
966+ // currently **NOT** allowed for (non-coercion) ptr-to-ptr casts (e.g
967+ // `*const Foo` to `*const Bar` where `Foo` has a `dyn Trait + Auto` tail
968+ // and `Bar` has a `dyn Auto` tail), because the underlying MIR operations
969+ // currently work very differently:
970+ //
971+ // * A MIR unsizing coercion on raw pointers to trait objects (`*const dyn Src`
972+ // to `*const dyn Dst`) is currently equivalent to downcasting the source to
973+ // the concrete sized type that it was originally unsized from first (via a
974+ // ptr-to-ptr cast from `*const Src` to `*const T` with `T: Sized`) and then
975+ // unsizing this thin pointer to the target type (unsizing `*const T` to
976+ // `*const Dst`). In particular, this means that the pointer's metadata
977+ // (vtable) will semantically change, e.g. for const eval and miri, even
978+ // though the vtables will always be merged for codegen.
979+ //
980+ // * A MIR ptr-to-ptr cast is currently equivalent to a transmute and does not
981+ // change the pointer metadata (vtable) at all.
982+ //
983+ // In addition to this potentially surprising difference between coercion and
984+ // non-coercion casts, casting away the principal with a MIR ptr-to-ptr cast
985+ // is currently considered undefined behavior:
986+ //
987+ // As a validity invariant of pointers to trait objects, we currently require
988+ // that the principal of the vtable in the pointer metadata exactly matches
989+ // the principal of the pointee type, where "no principal" is also considered
990+ // a kind of principal.
964991 ( Some ( _) , None ) => Err ( CastError :: DifferingKinds { src_kind, dst_kind } ) ,
965992
966993 // dyn Auto -> dyn Trait? not ok.
0 commit comments