@@ -100,10 +100,18 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
100
100
rematch_impl ( self , goal, def_id, nested_obligations)
101
101
}
102
102
103
+ // If an unsize goal is ambiguous, then we can manually rematch it to make
104
+ // selection progress for coercion during HIR typeck. If it is *not* ambiguous,
105
+ // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals,
106
+ // and we need to rematch those to detect tuple unsizing and trait upcasting.
107
+ // FIXME: This will be wrong if we have param-env or where-clause bounds
108
+ // with the unsize goal -- we may need to mark those with different impl
109
+ // sources.
103
110
( Certainty :: Maybe ( _) , CandidateSource :: BuiltinImpl ( src) )
111
+ | ( Certainty :: Yes , CandidateSource :: BuiltinImpl ( src @ BuiltinImplSource :: Misc ) )
104
112
if self . tcx . lang_items ( ) . unsize_trait ( ) == Some ( goal. predicate . def_id ( ) ) =>
105
113
{
106
- rematch_unsize ( self , goal, nested_obligations, src)
114
+ rematch_unsize ( self , goal, nested_obligations, src, certainty )
107
115
}
108
116
109
117
// Technically some builtin impls have nested obligations, but if
@@ -217,6 +225,7 @@ fn rematch_unsize<'tcx>(
217
225
goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
218
226
mut nested : Vec < PredicateObligation < ' tcx > > ,
219
227
source : BuiltinImplSource ,
228
+ certainty : Certainty ,
220
229
) -> SelectionResult < ' tcx , Selection < ' tcx > > {
221
230
let tcx = infcx. tcx ;
222
231
let a_ty = structurally_normalize ( goal. predicate . self_ty ( ) , infcx, goal. param_env , & mut nested) ;
@@ -227,6 +236,12 @@ fn rematch_unsize<'tcx>(
227
236
& mut nested,
228
237
) ;
229
238
match ( a_ty. kind ( ) , b_ty. kind ( ) ) {
239
+ // Stall any ambiguous upcasting goals, since we can't rematch those
240
+ ( ty:: Dynamic ( _, _, ty:: Dyn ) , ty:: Dynamic ( _, _, ty:: Dyn ) ) => match certainty {
241
+ Certainty :: Yes => Ok ( Some ( ImplSource :: Builtin ( source, nested) ) ) ,
242
+ _ => Ok ( None ) ,
243
+ } ,
244
+ // `T` -> `dyn Trait` upcasting
230
245
( _, & ty:: Dynamic ( data, region, ty:: Dyn ) ) => {
231
246
// Check that the type implements all of the predicates of the def-id.
232
247
// (i.e. the principal, all of the associated types match, and any auto traits)
@@ -354,10 +369,10 @@ fn rematch_unsize<'tcx>(
354
369
) ;
355
370
Ok ( Some ( ImplSource :: Builtin ( source, nested) ) )
356
371
}
357
- // FIXME: We *could* ICE here if either:
358
- // 1. the certainty is ` Certainty::Yes`,
359
- // 2. we're in codegen (which should mean `Certainty::Yes`).
360
- _ => Ok ( None ) ,
372
+ _ => {
373
+ assert_ne ! ( certainty, Certainty :: Yes ) ;
374
+ Ok ( None )
375
+ }
361
376
}
362
377
}
363
378
0 commit comments