@@ -315,6 +315,49 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
315315 // bounds. It might be the case that we want two distinct caches,
316316 // or else another kind of cache entry.
317317 let cache_entry = infcx. inner . borrow_mut ( ) . projection_cache ( ) . try_start ( cache_key) ;
318+ match cache_entry {
319+ // This is the hottest path in this function.
320+ //
321+ // If we find the value in the cache, then return it along with the
322+ // obligations that went along with it. Note that, when using a
323+ // fulfillment context, these obligations could in principle be
324+ // ignored: they have already been registered when the cache entry
325+ // was created (and hence the new ones will quickly be discarded as
326+ // duplicated). But when doing trait evaluation this is not the
327+ // case, and dropping the trait evaluations can causes ICEs (e.g.,
328+ // #43132).
329+ Err ( ProjectionCacheEntry :: NormalizedTerm { ty, complete : _ } ) => {
330+ debug ! ( ?ty, "found normalized ty" ) ;
331+ obligations. extend ( ty. obligations ) ;
332+ Ok ( Some ( ty. value ) )
333+ }
334+ cache_entry => opt_normalize_projection_term_slow (
335+ selcx,
336+ param_env,
337+ projection_term,
338+ cause,
339+ depth,
340+ obligations,
341+ cache_entry,
342+ cache_key,
343+ ) ,
344+ }
345+ }
346+
347+ /// Cold-path body of [`opt_normalize_projection_term`].
348+ #[ cold]
349+ #[ inline( never) ]
350+ fn opt_normalize_projection_term_slow < ' a , ' b , ' tcx > (
351+ selcx : & ' a mut SelectionContext < ' b , ' tcx > ,
352+ param_env : ty:: ParamEnv < ' tcx > ,
353+ projection_term : ty:: AliasTerm < ' tcx > ,
354+ cause : ObligationCause < ' tcx > ,
355+ depth : usize ,
356+ obligations : & mut PredicateObligations < ' tcx > ,
357+ cache_entry : Result < ( ) , ProjectionCacheEntry < ' tcx > > ,
358+ cache_key : ProjectionCacheKey < ' tcx > ,
359+ ) -> Result < Option < Term < ' tcx > > , InProgress > {
360+ let infcx = selcx. infcx ;
318361 match cache_entry {
319362 Ok ( ( ) ) => debug ! ( "no cache" ) ,
320363 Err ( ProjectionCacheEntry :: Ambiguous ) => {
@@ -345,21 +388,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
345388 debug ! ( "recur cache" ) ;
346389 return Err ( InProgress ) ;
347390 }
348- Err ( ProjectionCacheEntry :: NormalizedTerm { ty, complete : _ } ) => {
349- // This is the hottest path in this function.
350- //
351- // If we find the value in the cache, then return it along
352- // with the obligations that went along with it. Note
353- // that, when using a fulfillment context, these
354- // obligations could in principle be ignored: they have
355- // already been registered when the cache entry was
356- // created (and hence the new ones will quickly be
357- // discarded as duplicated). But when doing trait
358- // evaluation this is not the case, and dropping the trait
359- // evaluations can causes ICEs (e.g., #43132).
360- debug ! ( ?ty, "found normalized ty" ) ;
361- obligations. extend ( ty. obligations ) ;
362- return Ok ( Some ( ty. value ) ) ;
391+ Err ( ProjectionCacheEntry :: NormalizedTerm { .. } ) => {
392+ unreachable ! ( "NormalizedTerm cache hit should be handled by the hot dispatcher" ) ;
363393 }
364394 Err ( ProjectionCacheEntry :: Error ) => {
365395 debug ! ( "opt_normalize_projection_type: found error" ) ;
0 commit comments