@@ -625,6 +625,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
625
625
) ] ;
626
626
627
627
let mut has_unsized_tuple_coercion = false ;
628
+ let mut has_trait_upcasting_coercion = None ;
628
629
629
630
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
630
631
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
692
693
// these here and emit a feature error if coercion doesn't fail
693
694
// due to another reason.
694
695
match impl_source {
696
+ traits:: ImplSource :: Builtin (
697
+ BuiltinImplSource :: TraitUpcasting { .. } ,
698
+ _,
699
+ ) => {
700
+ has_trait_upcasting_coercion =
701
+ Some ( ( trait_pred. self_ty ( ) , trait_pred. trait_ref . args . type_at ( 1 ) ) ) ;
702
+ }
695
703
traits:: ImplSource :: Builtin ( BuiltinImplSource :: TupleUnsizing , _) => {
696
704
has_unsized_tuple_coercion = true ;
697
705
}
@@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
702
710
}
703
711
}
704
712
713
+ if let Some ( ( sub, sup) ) = has_trait_upcasting_coercion
714
+ && !self . tcx ( ) . features ( ) . trait_upcasting
715
+ {
716
+ // Renders better when we erase regions, since they're not really the point here.
717
+ let ( sub, sup) = self . tcx . erase_regions ( ( sub, sup) ) ;
718
+ let mut err = feature_err (
719
+ & self . tcx . sess ,
720
+ sym:: trait_upcasting,
721
+ self . cause . span ,
722
+ format ! ( "cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental" ) ,
723
+ ) ;
724
+ err. note ( format ! ( "required when coercing `{source}` into `{target}`" ) ) ;
725
+ err. emit ( ) ;
726
+ }
727
+
705
728
if has_unsized_tuple_coercion && !self . tcx . features ( ) . unsized_tuple_coercion {
706
729
feature_err (
707
730
& self . tcx . sess ,
0 commit comments