@@ -289,6 +289,10 @@ where
289289 D : SolverDelegate < Interner = I > ,
290290 I : Interner ,
291291{
292+ /// Helper function that first tries to normalize the self type of the goal, bailing with
293+ /// ambiguity if normalizing is ambiguous or if it bottoms out in an infer var, then calls
294+ /// the `assemble` callback. It additionally manages assembling a coherence-unknowable
295+ /// candidate if necessary, which takes precedence over all other candidates.
292296 fn assemble_and_evaluate_candidates_with_normalized_goal < G : GoalKind < D > > (
293297 & mut self ,
294298 goal : Goal < I , G > ,
@@ -326,12 +330,28 @@ where
326330 ) -> Vec < Candidate < I > > {
327331 self . assemble_and_evaluate_candidates_with_normalized_goal ( goal, |ecx, goal| {
328332 let mut candidates = vec ! [ ] ;
329- ecx. assemble_alias_bound_candidates ( goal, & mut candidates) ;
330- ecx. assemble_param_env_candidates ( goal, & mut candidates) ;
333+ // Only assemble candidates via this helper function, since its logic is shared with
334+ // `assemble_and_evaluate_candidates` below. Any other candidates that are only
335+ // assembled by this function (or only by `assemble_and_evaluate_candidates`) will be
336+ // subtly incomplete when it comes to normalizes-to goals.
337+ ecx. assemble_param_env_and_bound_candidates ( goal, & mut candidates) ;
338+ debug_assert ! ( candidates. iter( ) . all( |c| matches!(
339+ c. source,
340+ CandidateSource :: AliasBound | CandidateSource :: ParamEnv ( _)
341+ ) ) ) ;
331342 candidates
332343 } )
333344 }
334345
346+ fn assemble_param_env_and_bound_candidates < G : GoalKind < D > > (
347+ & mut self ,
348+ goal : Goal < I , G > ,
349+ candidates : & mut Vec < Candidate < I > > ,
350+ ) {
351+ self . assemble_alias_bound_candidates ( goal, candidates) ;
352+ self . assemble_param_env_candidates ( goal, candidates) ;
353+ }
354+
335355 pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < D > > (
336356 & mut self ,
337357 goal : Goal < I , G > ,
@@ -341,8 +361,16 @@ where
341361 ecx. assemble_impl_candidates ( goal, & mut candidates) ;
342362 ecx. assemble_builtin_impl_candidates ( goal, & mut candidates) ;
343363 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) ;
364+ // NOTE: Make sure that we're not assembling any param-env/bound candidates
365+ // outside of `assemble_param_env_and_bound_candidates`, since we want to make
366+ // sure not to *incompletely* assemble candidates in
367+ // `assemble_and_evaluate_candidates_from_env_and_bounds` which uses the helper
368+ // `assemble_param_env_and_bound_candidates`.
369+ debug_assert ! ( !candidates. iter( ) . any( |c| matches!(
370+ c. source,
371+ CandidateSource :: AliasBound | CandidateSource :: ParamEnv ( _)
372+ ) ) ) ;
373+ ecx. assemble_param_env_and_bound_candidates ( goal, & mut candidates) ;
346374 candidates
347375 } )
348376 }
@@ -766,6 +794,9 @@ where
766794 } )
767795 }
768796
797+ /// Assemble and merge candidates for goals which are related to an underlying trait
798+ /// goal. Right now, this is normalizes-to and host effect goals.
799+ ///
769800 /// We sadly can't simply take all possible candidates for normalization goals
770801 /// and check whether they result in the same constraints. We want to make sure
771802 /// that trying to normalize an alias doesn't result in constraints which aren't
@@ -804,7 +835,7 @@ where
804835 // We don't care about overflow. If proving the trait goal overflowed, then
805836 // it's enough to report an overflow error for that, we don't also have to
806837 // overflow during normalization.
807- return Ok ( self . make_ambiguous_response_no_constraints ( MaybeCause :: Ambiguity ) ) ;
838+ return Ok ( self . forced_ambiguity ( MaybeCause :: Ambiguity ) ? . result ) ;
808839 } ;
809840
810841 match proven_via {
@@ -815,11 +846,6 @@ where
815846 let candidates_from_env_and_bounds: Vec < _ > =
816847 self . assemble_and_evaluate_candidates_from_env_and_bounds ( goal) ;
817848
818- debug_assert ! ( candidates_from_env_and_bounds. iter( ) . all( |c| matches!(
819- c. source,
820- CandidateSource :: AliasBound | CandidateSource :: ParamEnv ( _)
821- ) ) ) ;
822-
823849 // We still need to prefer where-bounds over alias-bounds however.
824850 // See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
825851 let mut considered_candidates: Vec < _ > = if candidates_from_env_and_bounds
0 commit comments