@@ -289,9 +289,10 @@ where
289289 D : SolverDelegate < Interner = I > ,
290290 I : Interner ,
291291{
292- pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < D > > (
292+ fn assemble_and_evaluate_candidates_with_normalized_goal < G : GoalKind < D > > (
293293 & mut self ,
294294 goal : Goal < I , G > ,
295+ assemble : impl FnOnce ( & mut Self , Goal < I , G > ) -> Vec < Candidate < I > > ,
295296 ) -> Vec < Candidate < I > > {
296297 let Ok ( normalized_self_ty) =
297298 self . structurally_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
@@ -310,25 +311,40 @@ where
310311 // normalizing the self type as well, since type variables are not uniquified.
311312 let goal = self . resolve_vars_if_possible ( goal) ;
312313
313- let mut candidates = vec ! [ ] ;
314-
315314 if let TypingMode :: Coherence = self . typing_mode ( ) {
316315 if let Ok ( candidate) = self . consider_coherence_unknowable_candidate ( goal) {
317316 return vec ! [ candidate] ;
318317 }
319318 }
320319
321- self . assemble_impl_candidates ( goal, & mut candidates) ;
322-
323- self . assemble_builtin_impl_candidates ( goal, & mut candidates) ;
324-
325- self . assemble_alias_bound_candidates ( goal, & mut candidates) ;
326-
327- self . assemble_object_bound_candidates ( goal, & mut candidates) ;
320+ assemble ( self , goal)
321+ }
328322
329- self . assemble_param_env_candidates ( goal, & mut candidates) ;
323+ pub ( super ) fn assemble_and_evaluate_candidates_from_env_and_bounds < G : GoalKind < D > > (
324+ & mut self ,
325+ goal : Goal < I , G > ,
326+ ) -> Vec < Candidate < I > > {
327+ self . assemble_and_evaluate_candidates_with_normalized_goal ( goal, |ecx, goal| {
328+ let mut candidates = vec ! [ ] ;
329+ ecx. assemble_alias_bound_candidates ( goal, & mut candidates) ;
330+ ecx. assemble_param_env_candidates ( goal, & mut candidates) ;
331+ candidates
332+ } )
333+ }
330334
331- candidates
335+ pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < D > > (
336+ & mut self ,
337+ goal : Goal < I , G > ,
338+ ) -> Vec < Candidate < I > > {
339+ self . assemble_and_evaluate_candidates_with_normalized_goal ( goal, |ecx, goal| {
340+ let mut candidates = vec ! [ ] ;
341+ ecx. assemble_impl_candidates ( goal, & mut candidates) ;
342+ ecx. assemble_builtin_impl_candidates ( goal, & mut candidates) ;
343+ ecx. assemble_object_bound_candidates ( goal, & mut candidates) ;
344+ ecx. assemble_alias_bound_candidates ( goal, & mut candidates) ;
345+ ecx. assemble_param_env_candidates ( goal, & mut candidates) ;
346+ candidates
347+ } )
332348 }
333349
334350 pub ( super ) fn forced_ambiguity (
@@ -778,10 +794,10 @@ where
778794 ///
779795 /// See trait-system-refactor-initiative#124 for more details.
780796 #[ instrument( level = "debug" , skip( self , inject_normalize_to_rigid_candidate) , ret) ]
781- pub ( super ) fn merge_candidates (
797+ pub ( super ) fn assemble_and_merge_candidates < G : GoalKind < D > > (
782798 & mut self ,
783799 proven_via : Option < TraitGoalProvenVia > ,
784- candidates : Vec < Candidate < I > > ,
800+ goal : Goal < I , G > ,
785801 inject_normalize_to_rigid_candidate : impl FnOnce ( & mut EvalCtxt < ' _ , D > ) -> QueryResult < I > ,
786802 ) -> QueryResult < I > {
787803 let Some ( proven_via) = proven_via else {
@@ -793,32 +809,31 @@ where
793809
794810 match proven_via {
795811 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-
804812 // Even when a trait bound has been proven using a where-bound, we
805813 // still need to consider alias-bounds for normalization, see
806- // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
807- //
814+ // `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
815+ let candidates_from_env_and_bounds: Vec < _ > =
816+ self . assemble_and_evaluate_candidates_from_env_and_bounds ( goal) ;
817+
818+ debug_assert ! ( candidates_from_env_and_bounds. iter( ) . all( |c| matches!(
819+ c. source,
820+ CandidateSource :: AliasBound | CandidateSource :: ParamEnv ( _)
821+ ) ) ) ;
822+
808823 // 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- }
824+ // See ` tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs` .
825+ let mut considered_candidates : Vec < _ > = if candidates_from_env_and_bounds
826+ . iter ( )
827+ . any ( |c| matches ! ( c . source , CandidateSource :: ParamEnv ( _ ) ) )
828+ {
829+ candidates_from_env_and_bounds
830+ . into_iter ( )
831+ . filter ( |c| matches ! ( c . source , CandidateSource :: ParamEnv ( _ ) ) )
832+ . map ( |c| c . result )
833+ . collect ( )
834+ } else {
835+ candidates_from_env_and_bounds . into_iter ( ) . map ( |c| c . result ) . collect ( )
836+ } ;
822837
823838 // If the trait goal has been proven by using the environment, we want to treat
824839 // aliases as rigid if there are no applicable projection bounds in the environment.
@@ -835,6 +850,8 @@ where
835850 }
836851 }
837852 TraitGoalProvenVia :: Misc => {
853+ let candidates = self . assemble_and_evaluate_candidates ( goal) ;
854+
838855 // Prefer "orphaned" param-env normalization predicates, which are used
839856 // (for example, and ideally only) when proving item bounds for an impl.
840857 let candidates_from_env: Vec < _ > = candidates
0 commit comments