@@ -12,6 +12,7 @@ fn main() {
1212 drop_principal ( ) ;
1313 modulo_binder ( ) ;
1414 modulo_assoc ( ) ;
15+ bidirectional_subtyping ( ) ;
1516}
1617
1718fn vtable_nop_cast ( ) {
@@ -534,3 +535,32 @@ fn modulo_assoc() {
534535
535536 ( & ( ) as & dyn Trait as & dyn Middle < ( ) > ) . say_hello ( & 0 ) ;
536537}
538+
539+ fn bidirectional_subtyping ( ) {
540+ // Test that transmuting between subtypes of dyn traits is fine, even in the
541+ // "wrong direction", i.e. going from a lower-ranked to a higher-ranked dyn trait.
542+ // Note that compared to the `dyn-transmute-inner-binder` test, the `for` is on the
543+ // *outside* here!
544+
545+ trait Trait < U : ?Sized > { }
546+ impl < T , U : ?Sized > Trait < U > for T { }
547+
548+ struct Wrapper < T : ?Sized > ( T ) ;
549+
550+ let x: & dyn Trait < fn ( & ' static ( ) ) > = & ( ) ;
551+ let _y: & dyn for < ' a > Trait < fn ( & ' a ( ) ) > = unsafe { std:: mem:: transmute ( x) } ;
552+
553+ let x: & dyn for < ' a > Trait < fn ( & ' a ( ) ) > = & ( ) ;
554+ let _y: & dyn Trait < fn ( & ' static ( ) ) > = unsafe { std:: mem:: transmute ( x) } ;
555+
556+ let x: & dyn Trait < dyn Trait < fn ( & ' static ( ) ) > > = & ( ) ;
557+ let _y: & dyn for < ' a > Trait < dyn Trait < fn ( & ' a ( ) ) > > = unsafe { std:: mem:: transmute ( x) } ;
558+
559+ let x: & dyn for < ' a > Trait < dyn Trait < fn ( & ' a ( ) ) > > = & ( ) ;
560+ let _y: & dyn Trait < dyn Trait < fn ( & ' static ( ) ) > > = unsafe { std:: mem:: transmute ( x) } ;
561+
562+ // This lowers to a ptr-to-ptr cast (which behaves like a transmute)
563+ // and not an unsizing coercion:
564+ let x: * const dyn for < ' a > Trait < & ' a ( ) > = & ( ) ;
565+ let _y: * const Wrapper < dyn Trait < & ' static ( ) > > = x as _ ;
566+ }
0 commit comments