11//! Code shared by trait and projection goals for candidate assembly.
22
3- use super :: search_graph:: OverflowHandler ;
43use super :: { EvalCtxt , SolverMode } ;
54use crate :: traits:: coherence;
65use rustc_hir:: def_id:: DefId ;
@@ -315,7 +314,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
315314 return ambig;
316315 }
317316
318- let mut candidates = self . assemble_candidates_via_self_ty ( goal) ;
317+ let mut candidates = self . assemble_candidates_via_self_ty ( goal, 0 ) ;
319318
320319 self . assemble_blanket_impl_candidates ( goal, & mut candidates) ;
321320
@@ -351,6 +350,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
351350 fn assemble_candidates_via_self_ty < G : GoalKind < ' tcx > > (
352351 & mut self ,
353352 goal : Goal < ' tcx , G > ,
353+ num_steps : usize ,
354354 ) -> Vec < Candidate < ' tcx > > {
355355 debug_assert_eq ! ( goal, self . resolve_vars_if_possible( goal) ) ;
356356 if let Some ( ambig) = self . assemble_self_ty_infer_ambiguity_response ( goal) {
@@ -369,7 +369,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
369369
370370 self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
371371
372- self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates) ;
372+ self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates, num_steps ) ;
373373
374374 candidates
375375 }
@@ -393,49 +393,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
393393 & mut self ,
394394 goal : Goal < ' tcx , G > ,
395395 candidates : & mut Vec < Candidate < ' tcx > > ,
396+ num_steps : usize ,
396397 ) {
397398 let tcx = self . tcx ( ) ;
398399 let & ty:: Alias ( _, projection_ty) = goal. predicate . self_ty ( ) . kind ( ) else { return } ;
399400
400- let normalized_self_candidates: Result < _ , NoSolution > =
401- self . probe ( |_| CandidateKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
402- ecx. with_incremented_depth (
403- |ecx| {
404- let result = ecx. evaluate_added_goals_and_make_canonical_response (
405- Certainty :: OVERFLOW ,
406- ) ?;
407- Ok ( vec ! [ Candidate {
408- source: CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
409- result,
410- } ] )
411- } ,
412- |ecx| {
413- let normalized_ty = ecx. next_ty_infer ( ) ;
414- let normalizes_to_goal = goal. with (
415- tcx,
416- ty:: Binder :: dummy ( ty:: ProjectionPredicate {
417- projection_ty,
418- term : normalized_ty. into ( ) ,
419- } ) ,
420- ) ;
421- ecx. add_goal ( normalizes_to_goal) ;
422- let _ = ecx. try_evaluate_added_goals ( ) . inspect_err ( |_| {
423- debug ! ( "self type normalization failed" ) ;
424- } ) ?;
425- let normalized_ty = ecx. resolve_vars_if_possible ( normalized_ty) ;
426- debug ! ( ?normalized_ty, "self type normalized" ) ;
427- // NOTE: Alternatively we could call `evaluate_goal` here and only
428- // have a `Normalized` candidate. This doesn't work as long as we
429- // use `CandidateSource` in winnowing.
430- let goal = goal. with ( tcx, goal. predicate . with_self_ty ( tcx, normalized_ty) ) ;
431- Ok ( ecx. assemble_candidates_via_self_ty ( goal) )
432- } ,
433- )
434- } ) ;
435-
436- if let Ok ( normalized_self_candidates) = normalized_self_candidates {
437- candidates. extend ( normalized_self_candidates) ;
438- }
401+ candidates. extend ( self . probe ( |_| CandidateKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
402+ if num_steps < ecx. local_overflow_limit ( ) {
403+ let normalized_ty = ecx. next_ty_infer ( ) ;
404+ let normalizes_to_goal = goal. with (
405+ tcx,
406+ ty:: ProjectionPredicate { projection_ty, term : normalized_ty. into ( ) } ,
407+ ) ;
408+ ecx. add_goal ( normalizes_to_goal) ;
409+ if let Err ( NoSolution ) = ecx. try_evaluate_added_goals ( ) {
410+ debug ! ( "self type normalization failed" ) ;
411+ return vec ! [ ] ;
412+ }
413+ let normalized_ty = ecx. resolve_vars_if_possible ( normalized_ty) ;
414+ debug ! ( ?normalized_ty, "self type normalized" ) ;
415+ // NOTE: Alternatively we could call `evaluate_goal` here and only
416+ // have a `Normalized` candidate. This doesn't work as long as we
417+ // use `CandidateSource` in winnowing.
418+ let goal = goal. with ( tcx, goal. predicate . with_self_ty ( tcx, normalized_ty) ) ;
419+ ecx. assemble_candidates_via_self_ty ( goal, num_steps + 1 )
420+ } else {
421+ match ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: OVERFLOW ) {
422+ Ok ( result) => vec ! [ Candidate {
423+ source: CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
424+ result,
425+ } ] ,
426+ Err ( NoSolution ) => vec ! [ ] ,
427+ }
428+ }
429+ } ) ) ;
439430 }
440431
441432 #[ instrument( level = "debug" , skip_all) ]
@@ -533,7 +524,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
533524 ty:: Alias ( _, _) | ty:: Placeholder ( ..) | ty:: Error ( _) => ( ) ,
534525
535526 // FIXME: These should ideally not exist as a self type. It would be nice for
536- // the builtin auto trait impls of generators should instead directly recurse
527+ // the builtin auto trait impls of generators to instead directly recurse
537528 // into the witness.
538529 ty:: GeneratorWitness ( _) | ty:: GeneratorWitnessMIR ( _, _) => ( ) ,
539530
0 commit comments