@@ -16,8 +16,8 @@ use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes
1616use crate :: solve:: assembly:: { self , AllowInferenceConstraints , AssembleCandidatesFrom , Candidate } ;
1717use crate :: solve:: inspect:: ProbeKind ;
1818use crate :: solve:: {
19- BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , MaybeCause ,
20- NoSolution , ParamEnvSource , QueryResult , has_only_region_constraints,
19+ BuiltinImplSource , CandidateSource , Candidates , Certainty , EvalCtxt , Goal , GoalSource ,
20+ MaybeCause , NoSolution , ParamEnvSource , QueryResult , has_only_region_constraints,
2121} ;
2222
2323impl < D , I > assembly:: GoalKind < D > for TraitPredicate < I >
@@ -1343,22 +1343,20 @@ where
13431343 #[ instrument( level = "debug" , skip( self ) , ret) ]
13441344 pub ( super ) fn merge_trait_candidates (
13451345 & mut self ,
1346- mut candidates : Vec < Candidate < I > > ,
1346+ mut candidates : Candidates < I > ,
13471347 ) -> Result < ( CanonicalResponse < I > , Option < TraitGoalProvenVia > ) , NoSolution > {
13481348 if let TypingMode :: Coherence = self . typing_mode ( ) {
1349- let all_candidates: Vec < _ > = candidates. into_iter ( ) . map ( |c| c. result ) . collect ( ) ;
1350- return if let Some ( response) = self . try_merge_responses ( & all_candidates) {
1351- Ok ( ( response, Some ( TraitGoalProvenVia :: Misc ) ) )
1352- } else {
1353- self . flounder ( & all_candidates) . map ( |r| ( r, None ) )
1354- } ;
1349+ match self . try_merge_candidates ( candidates. applicable , vec ! [ ] ) {
1350+ Ok ( response) => return Ok ( ( response, Some ( TraitGoalProvenVia :: Misc ) ) ) ,
1351+ Err ( candidates) => return self . flounder ( & candidates) . map ( |r| ( r, None ) ) ,
1352+ }
13551353 }
13561354
13571355 // We prefer trivial builtin candidates, i.e. builtin impls without any
13581356 // nested requirements, over all others. This is a fix for #53123 and
13591357 // prevents where-bounds from accidentally extending the lifetime of a
13601358 // variable.
1361- let mut trivial_builtin_impls = candidates. iter ( ) . filter ( |c| {
1359+ let mut trivial_builtin_impls = candidates. applicable . iter ( ) . filter ( |c| {
13621360 matches ! ( c. source, CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Trivial ) )
13631361 } ) ;
13641362 if let Some ( candidate) = trivial_builtin_impls. next ( ) {
@@ -1371,57 +1369,56 @@ where
13711369 // If there are non-global where-bounds, prefer where-bounds
13721370 // (including global ones) over everything else.
13731371 let has_non_global_where_bounds = candidates
1372+ . applicable
13741373 . iter ( )
13751374 . any ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: NonGlobal ) ) ) ;
13761375 if has_non_global_where_bounds {
1377- let where_bounds: Vec < _ > = candidates
1378- . iter ( )
1379- . filter ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
1380- . map ( |c| c . result )
1381- . collect ( ) ;
1382- return if let Some ( response ) = self . try_merge_responses ( & where_bounds ) {
1383- Ok ( ( response , Some ( TraitGoalProvenVia :: ParamEnv ) ) )
1384- } else {
1385- Ok ( ( self . bail_with_ambiguity ( & where_bounds) , None ) )
1386- } ;
1376+ let mut where_bounds = candidates. applicable ;
1377+ for not_where_bound in
1378+ where_bounds . extract_if ( .. , |c| ! matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
1379+ {
1380+ self . ignore_candidate_usages ( not_where_bound . candidate_usages ) ;
1381+ }
1382+ match self . try_merge_candidates ( where_bounds , candidates . not_applicable_param_env ) {
1383+ Ok ( response ) => return Ok ( ( response , Some ( TraitGoalProvenVia :: ParamEnv ) ) ) ,
1384+ Err ( where_bounds ) => return Ok ( ( self . bail_with_ambiguity ( & where_bounds) , None ) ) ,
1385+ }
13871386 }
13881387
1389- if candidates. iter ( ) . any ( |c| matches ! ( c. source, CandidateSource :: AliasBound ) ) {
1388+ if candidates. applicable . iter ( ) . any ( |c| matches ! ( c. source, CandidateSource :: AliasBound ) ) {
13901389 let alias_bounds: Vec < _ > = candidates
1391- . iter ( )
1392- . filter ( |c| matches ! ( c. source, CandidateSource :: AliasBound ) )
1393- . map ( |c| c. result )
1390+ . applicable
1391+ . extract_if ( .., |c| matches ! ( c. source, CandidateSource :: AliasBound ) )
13941392 . collect ( ) ;
1395- return if let Some ( response) = self . try_merge_responses ( & alias_bounds) {
1396- Ok ( ( response, Some ( TraitGoalProvenVia :: AliasBound ) ) )
1397- } else {
1398- Ok ( ( self . bail_with_ambiguity ( & alias_bounds) , None ) )
1399- } ;
1393+ match self . try_merge_candidates ( alias_bounds, vec ! [ ] ) {
1394+ Ok ( response) => return Ok ( ( response, Some ( TraitGoalProvenVia :: AliasBound ) ) ) ,
1395+ Err ( alias_bounds) => return Ok ( ( self . bail_with_ambiguity ( & alias_bounds) , None ) ) ,
1396+ }
14001397 }
14011398
1402- self . filter_specialized_impls ( AllowInferenceConstraints :: No , & mut candidates) ;
1403- self . unsound_prefer_builtin_dyn_impl ( & mut candidates) ;
1399+ self . filter_specialized_impls ( AllowInferenceConstraints :: No , & mut candidates. applicable ) ;
1400+ self . unsound_prefer_builtin_dyn_impl ( & mut candidates. applicable ) ;
14041401
14051402 // If there are *only* global where bounds, then make sure to return that this
14061403 // is still reported as being proven-via the param-env so that rigid projections
14071404 // operate correctly. Otherwise, drop all global where-bounds before merging the
14081405 // remaining candidates.
14091406 let proven_via = if candidates
1407+ . applicable
14101408 . iter ( )
14111409 . all ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) )
14121410 {
14131411 TraitGoalProvenVia :: ParamEnv
14141412 } else {
14151413 candidates
1414+ . applicable
14161415 . retain ( |c| !matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) ) ;
14171416 TraitGoalProvenVia :: Misc
14181417 } ;
14191418
1420- let all_candidates: Vec < _ > = candidates. into_iter ( ) . map ( |c| c. result ) . collect ( ) ;
1421- if let Some ( response) = self . try_merge_responses ( & all_candidates) {
1422- Ok ( ( response, Some ( proven_via) ) )
1423- } else {
1424- self . flounder ( & all_candidates) . map ( |r| ( r, None ) )
1419+ match self . try_merge_candidates ( candidates. applicable , vec ! [ ] ) {
1420+ Ok ( response) => Ok ( ( response, Some ( proven_via) ) ) ,
1421+ Err ( candidates) => self . flounder ( & candidates) . map ( |r| ( r, None ) ) ,
14251422 }
14261423 }
14271424
0 commit comments