@@ -100,10 +100,18 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
100100 rematch_impl ( self , goal, def_id, nested_obligations)
101101 }
102102
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.
103110 ( Certainty :: Maybe ( _) , CandidateSource :: BuiltinImpl ( src) )
111+ | ( Certainty :: Yes , CandidateSource :: BuiltinImpl ( src @ BuiltinImplSource :: Misc ) )
104112 if self . tcx . lang_items ( ) . unsize_trait ( ) == Some ( goal. predicate . def_id ( ) ) =>
105113 {
106- rematch_unsize ( self , goal, nested_obligations, src)
114+ rematch_unsize ( self , goal, nested_obligations, src, certainty )
107115 }
108116
109117 // Technically some builtin impls have nested obligations, but if
@@ -217,6 +225,7 @@ fn rematch_unsize<'tcx>(
217225 goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
218226 mut nested : Vec < PredicateObligation < ' tcx > > ,
219227 source : BuiltinImplSource ,
228+ certainty : Certainty ,
220229) -> SelectionResult < ' tcx , Selection < ' tcx > > {
221230 let tcx = infcx. tcx ;
222231 let a_ty = structurally_normalize ( goal. predicate . self_ty ( ) , infcx, goal. param_env , & mut nested) ;
@@ -227,6 +236,12 @@ fn rematch_unsize<'tcx>(
227236 & mut nested,
228237 ) ;
229238 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
230245 ( _, & ty:: Dynamic ( data, region, ty:: Dyn ) ) => {
231246 // Check that the type implements all of the predicates of the def-id.
232247 // (i.e. the principal, all of the associated types match, and any auto traits)
@@ -354,10 +369,10 @@ fn rematch_unsize<'tcx>(
354369 ) ;
355370 Ok ( Some ( ImplSource :: Builtin ( source, nested) ) )
356371 }
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+ }
361376 }
362377}
363378
0 commit comments