@@ -8,6 +8,7 @@ use std::ops::ControlFlow;
8
8
use derive_where:: derive_where;
9
9
use rustc_type_ir:: inherent:: * ;
10
10
use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
11
+ use rustc_type_ir:: search_graph:: CandidateUsages ;
11
12
use rustc_type_ir:: solve:: SizedTraitKind ;
12
13
use rustc_type_ir:: {
13
14
self as ty, Interner , TypeFlags , TypeFoldable , TypeSuperVisitable , TypeVisitable ,
@@ -33,10 +34,11 @@ enum AliasBoundKind {
33
34
///
34
35
/// It consists of both the `source`, which describes how that goal would be proven,
35
36
/// and the `result` when using the given `source`.
36
- #[ derive_where( Clone , Debug ; I : Interner ) ]
37
+ #[ derive_where( Debug ; I : Interner ) ]
37
38
pub ( super ) struct Candidate < I : Interner > {
38
39
pub ( super ) source : CandidateSource < I > ,
39
40
pub ( super ) result : CanonicalResponse < I > ,
41
+ pub ( super ) candidate_usages : CandidateUsages ,
40
42
}
41
43
42
44
/// Methods used to assemble candidates for either trait or projection goals.
@@ -116,8 +118,11 @@ where
116
118
ecx : & mut EvalCtxt < ' _ , D > ,
117
119
goal : Goal < I , Self > ,
118
120
assumption : I :: Clause ,
119
- ) -> Result < Candidate < I > , NoSolution > {
120
- Self :: fast_reject_assumption ( ecx, goal, assumption) ?;
121
+ ) -> Result < Candidate < I > , CandidateUsages > {
122
+ match Self :: fast_reject_assumption ( ecx, goal, assumption) {
123
+ Ok ( ( ) ) => { }
124
+ Err ( NoSolution ) => return Err ( CandidateUsages :: default ( ) ) ,
125
+ }
121
126
122
127
// Dealing with `ParamEnv` candidates is a bit of a mess as we need to lazily
123
128
// check whether the candidate is global while considering normalization.
@@ -126,18 +131,23 @@ where
126
131
// in `probe` even if the candidate does not apply before we get there. We handle this
127
132
// by using a `Cell` here. We only ever write into it inside of `match_assumption`.
128
133
let source = Cell :: new ( CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) ;
129
- ecx. probe ( |result : & QueryResult < I > | inspect:: ProbeKind :: TraitCandidate {
130
- source : source. get ( ) ,
131
- result : * result,
132
- } )
133
- . enter ( |ecx| {
134
- Self :: match_assumption ( ecx, goal, assumption, |ecx| {
135
- ecx. try_evaluate_added_goals ( ) ?;
136
- source. set ( ecx. characterize_param_env_assumption ( goal. param_env , assumption) ?) ;
137
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
134
+ let ( result, candidate_usages) = ecx
135
+ . probe ( |result : & QueryResult < I > | inspect:: ProbeKind :: TraitCandidate {
136
+ source : source. get ( ) ,
137
+ result : * result,
138
138
} )
139
- } )
140
- . map ( |result| Candidate { source : source. get ( ) , result } )
139
+ . enter_unique_candidate ( |ecx| {
140
+ Self :: match_assumption ( ecx, goal, assumption, |ecx| {
141
+ ecx. try_evaluate_added_goals ( ) ?;
142
+ source. set ( ecx. characterize_param_env_assumption ( goal. param_env , assumption) ?) ;
143
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
144
+ } )
145
+ } ) ;
146
+
147
+ match result {
148
+ Ok ( result) => Ok ( Candidate { source : source. get ( ) , result, candidate_usages } ) ,
149
+ Err ( NoSolution ) => Err ( candidate_usages) ,
150
+ }
141
151
}
142
152
143
153
/// Try equating an assumption predicate against a goal's predicate. If it
@@ -355,6 +365,12 @@ pub(super) enum AssembleCandidatesFrom {
355
365
EnvAndBounds ,
356
366
}
357
367
368
+ #[ derive_where( Debug , Default ; I : Interner ) ]
369
+ pub ( super ) struct Candidates < I : Interner > {
370
+ pub applicable : Vec < Candidate < I > > ,
371
+ pub not_applicable_param_env : Vec < CandidateUsages > ,
372
+ }
373
+
358
374
impl < D , I > EvalCtxt < ' _ , D >
359
375
where
360
376
D : SolverDelegate < Interner = I > ,
@@ -364,16 +380,18 @@ where
364
380
& mut self ,
365
381
goal : Goal < I , G > ,
366
382
assemble_from : AssembleCandidatesFrom ,
367
- ) -> Vec < Candidate < I > > {
383
+ ) -> Candidates < I > {
384
+ let mut candidates = Candidates :: default ( ) ;
368
385
let Ok ( normalized_self_ty) =
369
386
self . structurally_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
370
387
else {
371
- return vec ! [ ] ;
388
+ return candidates ;
372
389
} ;
373
390
374
391
if normalized_self_ty. is_ty_var ( ) {
375
392
debug ! ( "self type has been normalized to infer" ) ;
376
- return self . forced_ambiguity ( MaybeCause :: Ambiguity ) . into_iter ( ) . collect ( ) ;
393
+ candidates. applicable . extend ( self . forced_ambiguity ( MaybeCause :: Ambiguity ) ) ;
394
+ return candidates;
377
395
}
378
396
379
397
let goal: Goal < I , G > = goal
@@ -382,12 +400,11 @@ where
382
400
// normalizing the self type as well, since type variables are not uniquified.
383
401
let goal = self . resolve_vars_if_possible ( goal) ;
384
402
385
- let mut candidates = vec ! [ ] ;
386
-
387
403
if let TypingMode :: Coherence = self . typing_mode ( )
388
404
&& let Ok ( candidate) = self . consider_coherence_unknowable_candidate ( goal)
389
405
{
390
- return vec ! [ candidate] ;
406
+ candidates. applicable . push ( candidate) ;
407
+ return candidates;
391
408
}
392
409
393
410
self . assemble_alias_bound_candidates ( goal, & mut candidates) ;
@@ -408,7 +425,7 @@ where
408
425
// to worry about causing major performance regressions when doing so.
409
426
// See trait-system-refactor-initiative#226 for some ideas here.
410
427
if TypingMode :: Coherence == self . typing_mode ( )
411
- || !candidates. iter ( ) . any ( |c| {
428
+ || !candidates. applicable . iter ( ) . any ( |c| {
412
429
matches ! (
413
430
c. source,
414
431
CandidateSource :: ParamEnv ( ParamEnvSource :: NonGlobal )
@@ -445,7 +462,7 @@ where
445
462
fn assemble_impl_candidates < G : GoalKind < D > > (
446
463
& mut self ,
447
464
goal : Goal < I , G > ,
448
- candidates : & mut Vec < Candidate < I > > ,
465
+ candidates : & mut Candidates < I > ,
449
466
) {
450
467
let cx = self . cx ( ) ;
451
468
cx. for_each_relevant_impl (
@@ -460,7 +477,7 @@ where
460
477
}
461
478
462
479
match G :: consider_impl_candidate ( self , goal, impl_def_id) {
463
- Ok ( candidate) => candidates. push ( candidate) ,
480
+ Ok ( candidate) => candidates. applicable . push ( candidate) ,
464
481
Err ( NoSolution ) => ( ) ,
465
482
}
466
483
} ,
@@ -471,7 +488,7 @@ where
471
488
fn assemble_builtin_impl_candidates < G : GoalKind < D > > (
472
489
& mut self ,
473
490
goal : Goal < I , G > ,
474
- candidates : & mut Vec < Candidate < I > > ,
491
+ candidates : & mut Candidates < I > ,
475
492
) {
476
493
let cx = self . cx ( ) ;
477
494
let trait_def_id = goal. predicate . trait_def_id ( cx) ;
@@ -570,31 +587,36 @@ where
570
587
}
571
588
} ;
572
589
573
- candidates. extend ( result) ;
590
+ candidates. applicable . extend ( result) ;
574
591
575
592
// There may be multiple unsize candidates for a trait with several supertraits:
576
593
// `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
577
594
if cx. is_lang_item ( trait_def_id, TraitSolverLangItem :: Unsize ) {
578
- candidates. extend ( G :: consider_structural_builtin_unsize_candidates ( self , goal) ) ;
595
+ candidates
596
+ . applicable
597
+ . extend ( G :: consider_structural_builtin_unsize_candidates ( self , goal) ) ;
579
598
}
580
599
}
581
600
582
601
#[ instrument( level = "trace" , skip_all) ]
583
602
fn assemble_param_env_candidates < G : GoalKind < D > > (
584
603
& mut self ,
585
604
goal : Goal < I , G > ,
586
- candidates : & mut Vec < Candidate < I > > ,
605
+ candidates : & mut Candidates < I > ,
587
606
) {
588
607
for assumption in goal. param_env . caller_bounds ( ) . iter ( ) {
589
- candidates. extend ( G :: probe_and_consider_param_env_candidate ( self , goal, assumption) ) ;
608
+ match G :: probe_and_consider_param_env_candidate ( self , goal, assumption) {
609
+ Ok ( candidate) => candidates. applicable . push ( candidate) ,
610
+ Err ( candidate_usages) => candidates. not_applicable_param_env . push ( candidate_usages) ,
611
+ }
590
612
}
591
613
}
592
614
593
615
#[ instrument( level = "trace" , skip_all) ]
594
616
fn assemble_alias_bound_candidates < G : GoalKind < D > > (
595
617
& mut self ,
596
618
goal : Goal < I , G > ,
597
- candidates : & mut Vec < Candidate < I > > ,
619
+ candidates : & mut Candidates < I > ,
598
620
) {
599
621
let ( ) = self . probe ( |_| ProbeKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
600
622
ecx. assemble_alias_bound_candidates_recur (
@@ -619,7 +641,7 @@ where
619
641
& mut self ,
620
642
self_ty : I :: Ty ,
621
643
goal : Goal < I , G > ,
622
- candidates : & mut Vec < Candidate < I > > ,
644
+ candidates : & mut Candidates < I > ,
623
645
consider_self_bounds : AliasBoundKind ,
624
646
) {
625
647
let ( kind, alias_ty) = match self_ty. kind ( ) {
@@ -661,7 +683,11 @@ where
661
683
if let Ok ( result) =
662
684
self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
663
685
{
664
- candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
686
+ candidates. applicable . push ( Candidate {
687
+ source : CandidateSource :: AliasBound ,
688
+ result,
689
+ candidate_usages : CandidateUsages :: default ( ) ,
690
+ } ) ;
665
691
}
666
692
return ;
667
693
}
@@ -680,7 +706,7 @@ where
680
706
. item_self_bounds ( alias_ty. def_id )
681
707
. iter_instantiated ( self . cx ( ) , alias_ty. args )
682
708
{
683
- candidates. extend ( G :: probe_and_consider_implied_clause (
709
+ candidates. applicable . extend ( G :: probe_and_consider_implied_clause (
684
710
self ,
685
711
CandidateSource :: AliasBound ,
686
712
goal,
@@ -695,7 +721,7 @@ where
695
721
. item_non_self_bounds ( alias_ty. def_id )
696
722
. iter_instantiated ( self . cx ( ) , alias_ty. args )
697
723
{
698
- candidates. extend ( G :: probe_and_consider_implied_clause (
724
+ candidates. applicable . extend ( G :: probe_and_consider_implied_clause (
699
725
self ,
700
726
CandidateSource :: AliasBound ,
701
727
goal,
@@ -706,7 +732,9 @@ where
706
732
}
707
733
}
708
734
709
- candidates. extend ( G :: consider_additional_alias_assumptions ( self , goal, alias_ty) ) ;
735
+ candidates
736
+ . applicable
737
+ . extend ( G :: consider_additional_alias_assumptions ( self , goal, alias_ty) ) ;
710
738
711
739
if kind != ty:: Projection {
712
740
return ;
@@ -728,7 +756,7 @@ where
728
756
fn assemble_object_bound_candidates < G : GoalKind < D > > (
729
757
& mut self ,
730
758
goal : Goal < I , G > ,
731
- candidates : & mut Vec < Candidate < I > > ,
759
+ candidates : & mut Candidates < I > ,
732
760
) {
733
761
let cx = self . cx ( ) ;
734
762
if !cx. trait_may_be_implemented_via_object ( goal. predicate . trait_def_id ( cx) ) {
@@ -784,7 +812,7 @@ where
784
812
}
785
813
ty:: ExistentialPredicate :: Projection ( _)
786
814
| ty:: ExistentialPredicate :: AutoTrait ( _) => {
787
- candidates. extend ( G :: probe_and_consider_object_bound_candidate (
815
+ candidates. applicable . extend ( G :: probe_and_consider_object_bound_candidate (
788
816
self ,
789
817
CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
790
818
goal,
@@ -800,7 +828,7 @@ where
800
828
if let Some ( principal) = bounds. principal ( ) {
801
829
let principal_trait_ref = principal. with_self_ty ( cx, self_ty) ;
802
830
for ( idx, assumption) in elaborate:: supertraits ( cx, principal_trait_ref) . enumerate ( ) {
803
- candidates. extend ( G :: probe_and_consider_object_bound_candidate (
831
+ candidates. applicable . extend ( G :: probe_and_consider_object_bound_candidate (
804
832
self ,
805
833
CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Object ( idx) ) ,
806
834
goal,
@@ -959,24 +987,30 @@ where
959
987
// Even when a trait bound has been proven using a where-bound, we
960
988
// still need to consider alias-bounds for normalization, see
961
989
// `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
962
- let mut candidates: Vec < _ > = self
990
+ let mut candidates = self
963
991
. assemble_and_evaluate_candidates ( goal, AssembleCandidatesFrom :: EnvAndBounds ) ;
964
992
965
993
// We still need to prefer where-bounds over alias-bounds however.
966
994
// See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
967
- if candidates. iter ( ) . any ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) ) {
968
- candidates. retain ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) ) ;
969
- } else if candidates. is_empty ( ) {
995
+ if candidates
996
+ . applicable
997
+ . iter ( )
998
+ . any ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
999
+ {
1000
+ for ignored in candidates
1001
+ . applicable
1002
+ . extract_if ( .., |c| !matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
1003
+ {
1004
+ self . ignore_candidate_usages ( ignored. candidate_usages ) ;
1005
+ }
1006
+ } else if candidates. applicable . is_empty ( ) {
970
1007
// If the trait goal has been proven by using the environment, we want to treat
971
1008
// aliases as rigid if there are no applicable projection bounds in the environment.
972
1009
return inject_normalize_to_rigid_candidate ( self ) ;
973
1010
}
974
1011
975
- if let Some ( response) = self . try_merge_candidates ( & candidates) {
976
- Ok ( response)
977
- } else {
978
- self . flounder ( & candidates)
979
- }
1012
+ self . try_merge_candidates ( candidates. applicable , vec ! [ ] )
1013
+ . or_else ( |candidates| self . flounder ( & candidates) )
980
1014
}
981
1015
TraitGoalProvenVia :: Misc => {
982
1016
let mut candidates =
@@ -985,23 +1019,31 @@ where
985
1019
// Prefer "orphaned" param-env normalization predicates, which are used
986
1020
// (for example, and ideally only) when proving item bounds for an impl.
987
1021
let candidates_from_env: Vec < _ > = candidates
1022
+ . applicable
988
1023
. extract_if ( .., |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
989
1024
. collect ( ) ;
990
- if let Some ( response) = self . try_merge_candidates ( & candidates_from_env) {
991
- return Ok ( response) ;
1025
+ if !candidates_from_env. is_empty ( ) {
1026
+ match self . try_merge_candidates (
1027
+ candidates_from_env,
1028
+ candidates. not_applicable_param_env ,
1029
+ ) {
1030
+ Ok ( response) => return Ok ( response) ,
1031
+ Err ( candidates_from_env) => return self . flounder ( & candidates_from_env) ,
1032
+ }
992
1033
}
993
1034
994
1035
// We drop specialized impls to allow normalization via a final impl here. In case
995
1036
// the specializing impl has different inference constraints from the specialized
996
1037
// impl, proving the trait goal is already ambiguous, so we never get here. This
997
1038
// means we can just ignore inference constraints and don't have to special-case
998
1039
// constraining the normalized-to `term`.
999
- self . filter_specialized_impls ( AllowInferenceConstraints :: Yes , & mut candidates) ;
1000
- if let Some ( response) = self . try_merge_candidates ( & candidates) {
1001
- Ok ( response)
1002
- } else {
1003
- self . flounder ( & candidates)
1004
- }
1040
+ self . filter_specialized_impls (
1041
+ AllowInferenceConstraints :: Yes ,
1042
+ & mut candidates. applicable ,
1043
+ ) ;
1044
+
1045
+ self . try_merge_candidates ( candidates. applicable , vec ! [ ] )
1046
+ . or_else ( |candidates| self . flounder ( & candidates) )
1005
1047
}
1006
1048
}
1007
1049
}
0 commit comments