1
1
//! Code shared by trait and projection goals for candidate assembly.
2
2
3
- use super :: search_graph:: OverflowHandler ;
4
3
use super :: { EvalCtxt , SolverMode } ;
5
4
use crate :: traits:: coherence;
6
5
use rustc_hir:: def_id:: DefId ;
@@ -315,7 +314,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
315
314
return ambig;
316
315
}
317
316
318
- let mut candidates = self . assemble_candidates_via_self_ty ( goal) ;
317
+ let mut candidates = self . assemble_candidates_via_self_ty ( goal, 0 ) ;
319
318
320
319
self . assemble_blanket_impl_candidates ( goal, & mut candidates) ;
321
320
@@ -351,6 +350,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
351
350
fn assemble_candidates_via_self_ty < G : GoalKind < ' tcx > > (
352
351
& mut self ,
353
352
goal : Goal < ' tcx , G > ,
353
+ num_steps : usize ,
354
354
) -> Vec < Candidate < ' tcx > > {
355
355
debug_assert_eq ! ( goal, self . resolve_vars_if_possible( goal) ) ;
356
356
if let Some ( ambig) = self . assemble_self_ty_infer_ambiguity_response ( goal) {
@@ -369,7 +369,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
369
369
370
370
self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
371
371
372
- self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates) ;
372
+ self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates, num_steps ) ;
373
373
374
374
candidates
375
375
}
@@ -393,49 +393,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
393
393
& mut self ,
394
394
goal : Goal < ' tcx , G > ,
395
395
candidates : & mut Vec < Candidate < ' tcx > > ,
396
+ num_steps : usize ,
396
397
) {
397
398
let tcx = self . tcx ( ) ;
398
399
let & ty:: Alias ( _, projection_ty) = goal. predicate . self_ty ( ) . kind ( ) else { return } ;
399
400
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
+ } ) ) ;
439
430
}
440
431
441
432
#[ instrument( level = "debug" , skip_all) ]
@@ -533,7 +524,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
533
524
ty:: Alias ( _, _) | ty:: Placeholder ( ..) | ty:: Error ( _) => ( ) ,
534
525
535
526
// 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
537
528
// into the witness.
538
529
ty:: GeneratorWitness ( _) | ty:: GeneratorWitnessMIR ( _, _) => ( ) ,
539
530
0 commit comments