@@ -625,6 +625,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
625625 ) ] ;
626626
627627 let mut has_unsized_tuple_coercion = false ;
628+ let mut has_trait_upcasting_coercion = None ;
628629
629630 // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
630631 // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
692693 // these here and emit a feature error if coercion doesn't fail
693694 // due to another reason.
694695 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+ }
695703 traits:: ImplSource :: Builtin ( BuiltinImplSource :: TupleUnsizing , _) => {
696704 has_unsized_tuple_coercion = true ;
697705 }
@@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
702710 }
703711 }
704712
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+
705728 if has_unsized_tuple_coercion && !self . tcx . features ( ) . unsized_tuple_coercion {
706729 feature_err (
707730 & self . tcx . sess ,
0 commit comments