@@ -284,6 +284,14 @@ where
284
284
) -> Vec < Candidate < I > > ;
285
285
}
286
286
287
+ pub ( super ) enum AssembleCandidatesFrom {
288
+ All ,
289
+ /// Only assemble candidates from the environment and alias bounds, ignoring
290
+ /// /user-written and built-in impls. We only expect `ParamEnv` and `AliasBound`
291
+ /// candidates to be assembled.
292
+ EnvAndBounds ,
293
+ }
294
+
287
295
impl < D , I > EvalCtxt < ' _ , D >
288
296
where
289
297
D : SolverDelegate < Interner = I > ,
@@ -292,6 +300,7 @@ where
292
300
pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < D > > (
293
301
& mut self ,
294
302
goal : Goal < I , G > ,
303
+ assemble_from : AssembleCandidatesFrom ,
295
304
) -> Vec < Candidate < I > > {
296
305
let Ok ( normalized_self_ty) =
297
306
self . structurally_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
@@ -318,16 +327,18 @@ where
318
327
}
319
328
}
320
329
321
- self . assemble_impl_candidates ( goal, & mut candidates) ;
322
-
323
- self . assemble_builtin_impl_candidates ( goal, & mut candidates) ;
324
-
325
330
self . assemble_alias_bound_candidates ( goal, & mut candidates) ;
326
-
327
- self . assemble_object_bound_candidates ( goal, & mut candidates) ;
328
-
329
331
self . assemble_param_env_candidates ( goal, & mut candidates) ;
330
332
333
+ match assemble_from {
334
+ AssembleCandidatesFrom :: All => {
335
+ self . assemble_impl_candidates ( goal, & mut candidates) ;
336
+ self . assemble_builtin_impl_candidates ( goal, & mut candidates) ;
337
+ self . assemble_object_bound_candidates ( goal, & mut candidates) ;
338
+ }
339
+ AssembleCandidatesFrom :: EnvAndBounds => { }
340
+ }
341
+
331
342
candidates
332
343
}
333
344
@@ -750,6 +761,9 @@ where
750
761
} )
751
762
}
752
763
764
+ /// Assemble and merge candidates for goals which are related to an underlying trait
765
+ /// goal. Right now, this is normalizes-to and host effect goals.
766
+ ///
753
767
/// We sadly can't simply take all possible candidates for normalization goals
754
768
/// and check whether they result in the same constraints. We want to make sure
755
769
/// that trying to normalize an alias doesn't result in constraints which aren't
@@ -778,47 +792,41 @@ where
778
792
///
779
793
/// See trait-system-refactor-initiative#124 for more details.
780
794
#[ instrument( level = "debug" , skip( self , inject_normalize_to_rigid_candidate) , ret) ]
781
- pub ( super ) fn merge_candidates (
795
+ pub ( super ) fn assemble_and_merge_candidates < G : GoalKind < D > > (
782
796
& mut self ,
783
797
proven_via : Option < TraitGoalProvenVia > ,
784
- candidates : Vec < Candidate < I > > ,
798
+ goal : Goal < I , G > ,
785
799
inject_normalize_to_rigid_candidate : impl FnOnce ( & mut EvalCtxt < ' _ , D > ) -> QueryResult < I > ,
786
800
) -> QueryResult < I > {
787
801
let Some ( proven_via) = proven_via else {
788
802
// We don't care about overflow. If proving the trait goal overflowed, then
789
803
// it's enough to report an overflow error for that, we don't also have to
790
804
// overflow during normalization.
791
- return Ok ( self . make_ambiguous_response_no_constraints ( MaybeCause :: Ambiguity ) ) ;
805
+ return Ok ( self . forced_ambiguity ( MaybeCause :: Ambiguity ) ? . result ) ;
792
806
} ;
793
807
794
808
match proven_via {
795
809
TraitGoalProvenVia :: ParamEnv | TraitGoalProvenVia :: AliasBound => {
796
- let mut considered_candidates = Vec :: new ( ) ;
797
- considered_candidates. extend (
798
- candidates
799
- . iter ( )
800
- . filter ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
801
- . map ( |c| c. result ) ,
802
- ) ;
803
-
804
810
// Even when a trait bound has been proven using a where-bound, we
805
811
// still need to consider alias-bounds for normalization, see
806
- // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
807
- //
812
+ // `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
813
+ let candidates_from_env_and_bounds: Vec < _ > = self
814
+ . assemble_and_evaluate_candidates ( goal, AssembleCandidatesFrom :: EnvAndBounds ) ;
815
+
808
816
// We still need to prefer where-bounds over alias-bounds however.
809
- // See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs.
810
- //
811
- // FIXME(const_trait_impl): should this behavior also be used by
812
- // constness checking. Doing so is *at least theoretically* breaking,
813
- // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
814
- if considered_candidates . is_empty ( ) {
815
- considered_candidates . extend (
816
- candidates
817
- . iter ( )
818
- . filter ( |c| matches ! ( c . source , CandidateSource :: AliasBound ) )
819
- . map ( |c| c . result ) ,
820
- ) ;
821
- }
817
+ // See ` tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs` .
818
+ let mut considered_candidates : Vec < _ > = if candidates_from_env_and_bounds
819
+ . iter ( )
820
+ . any ( |c| matches ! ( c . source , CandidateSource :: ParamEnv ( _ ) ) )
821
+ {
822
+ candidates_from_env_and_bounds
823
+ . into_iter ( )
824
+ . filter ( |c| matches ! ( c . source , CandidateSource :: ParamEnv ( _ ) ) )
825
+ . map ( |c| c . result )
826
+ . collect ( )
827
+ } else {
828
+ candidates_from_env_and_bounds . into_iter ( ) . map ( |c| c . result ) . collect ( )
829
+ } ;
822
830
823
831
// If the trait goal has been proven by using the environment, we want to treat
824
832
// aliases as rigid if there are no applicable projection bounds in the environment.
@@ -835,6 +843,9 @@ where
835
843
}
836
844
}
837
845
TraitGoalProvenVia :: Misc => {
846
+ let candidates =
847
+ self . assemble_and_evaluate_candidates ( goal, AssembleCandidatesFrom :: All ) ;
848
+
838
849
// Prefer "orphaned" param-env normalization predicates, which are used
839
850
// (for example, and ideally only) when proving item bounds for an impl.
840
851
let candidates_from_env: Vec < _ > = candidates
0 commit comments