@@ -1183,21 +1183,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1183
1183
return ;
1184
1184
}
1185
1185
1186
+ let tcx = self . tcx ( ) ;
1186
1187
if let ty:: Adt ( src_def, src_args) = source. kind ( )
1187
1188
&& let ty:: Adt ( tgt_def, tgt_args) = target. kind ( )
1188
1189
&& 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 ( )
1190
1191
{
1191
1192
let src_dyn = src_args. type_at ( 0 ) ;
1192
1193
let tgt_dyn = tgt_args. type_at ( 0 ) ;
1193
1194
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 ( )
1199
1197
{
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
+ }
1201
1227
return ;
1202
1228
}
1203
1229
}
0 commit comments