@@ -1183,21 +1183,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11831183 return ;
11841184 }
11851185
1186+ let tcx = self . tcx ( ) ;
11861187 if let ty:: Adt ( src_def, src_args) = source. kind ( )
11871188 && let ty:: Adt ( tgt_def, tgt_args) = target. kind ( )
11881189 && src_def == tgt_def
1189- && Some ( src_def. did ( ) ) == self . tcx ( ) . lang_items ( ) . dyn_metadata ( )
1190+ && Some ( src_def. did ( ) ) == tcx. lang_items ( ) . dyn_metadata ( )
11901191 {
11911192 let src_dyn = src_args. type_at ( 0 ) ;
11921193 let tgt_dyn = tgt_args. type_at ( 0 ) ;
11931194
1194- // We could theoretically allow casting the principal away, but `as` casts
1195- // don't allow that, so neither does `MetadataCast` for now.
1196- if let ty:: Dynamic ( src_pred, _, ty:: Dyn ) = src_dyn. kind ( )
1197- && let ty:: Dynamic ( tgt_pred, _, ty:: Dyn ) = tgt_dyn. kind ( )
1198- && src_pred. principal_def_id ( ) == tgt_pred. principal_def_id ( )
1195+ if let ty:: Dynamic ( src_preds, _, ty:: Dyn ) = src_dyn. kind ( )
1196+ && let ty:: Dynamic ( tgt_preds, _, ty:: Dyn ) = tgt_dyn. kind ( )
11991197 {
1200- candidates. vec . push ( MetadataCastCandidate ( MetadataCastKind :: Unconditional ) ) ;
1198+ let mut src_traits = src_preds. auto_traits ( ) . collect :: < Vec < _ > > ( ) ;
1199+
1200+ if let Some ( src_principal_did) = src_preds. principal_def_id ( ) {
1201+ src_traits. extend ( tcx. super_traits_of ( src_principal_did) ) ;
1202+ }
1203+
1204+ for tgt_auto_trait in tgt_preds. auto_traits ( ) {
1205+ if !src_traits. contains ( & tgt_auto_trait) {
1206+ // Adding auto traits that aren't on the source or implied by
1207+ // the source principal is not allowed.
1208+ return ;
1209+ }
1210+ }
1211+
1212+ if let Some ( src_principal) = src_preds. principal ( ) {
1213+ if let Some ( tgt_principal) = tgt_preds. principal ( ) {
1214+ candidates. vec . push ( MetadataCastCandidate ( MetadataCastKind :: Dyn (
1215+ src_principal,
1216+ tgt_principal,
1217+ ) ) ) ;
1218+ } else {
1219+ // We could theoretically allow casting the principal away, but `as` casts
1220+ // don't allow that, so neither does `MetadataCast` for now.
1221+ }
1222+ } else if tgt_preds. principal ( ) . is_none ( ) {
1223+ // Casting between auto-trait-only trait objects is allowed if the target
1224+ // traits are a subset of the source traits, which we checked above.
1225+ candidates. vec . push ( MetadataCastCandidate ( MetadataCastKind :: Unconditional ) ) ;
1226+ }
12011227 return ;
12021228 }
12031229 }
0 commit comments