@@ -16,8 +16,8 @@ use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes
16
16
use crate :: solve:: assembly:: { self , AllowInferenceConstraints , AssembleCandidatesFrom , Candidate } ;
17
17
use crate :: solve:: inspect:: ProbeKind ;
18
18
use 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,
21
21
} ;
22
22
23
23
impl < D , I > assembly:: GoalKind < D > for TraitPredicate < I >
@@ -1343,22 +1343,20 @@ where
1343
1343
#[ instrument( level = "debug" , skip( self ) , ret) ]
1344
1344
pub ( super ) fn merge_trait_candidates (
1345
1345
& mut self ,
1346
- mut candidates : Vec < Candidate < I > > ,
1346
+ mut candidates : Candidates < I > ,
1347
1347
) -> Result < ( CanonicalResponse < I > , Option < TraitGoalProvenVia > ) , NoSolution > {
1348
1348
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
+ }
1355
1353
}
1356
1354
1357
1355
// We prefer trivial builtin candidates, i.e. builtin impls without any
1358
1356
// nested requirements, over all others. This is a fix for #53123 and
1359
1357
// prevents where-bounds from accidentally extending the lifetime of a
1360
1358
// variable.
1361
- let mut trivial_builtin_impls = candidates. iter ( ) . filter ( |c| {
1359
+ let mut trivial_builtin_impls = candidates. applicable . iter ( ) . filter ( |c| {
1362
1360
matches ! ( c. source, CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Trivial ) )
1363
1361
} ) ;
1364
1362
if let Some ( candidate) = trivial_builtin_impls. next ( ) {
@@ -1371,57 +1369,56 @@ where
1371
1369
// If there are non-global where-bounds, prefer where-bounds
1372
1370
// (including global ones) over everything else.
1373
1371
let has_non_global_where_bounds = candidates
1372
+ . applicable
1374
1373
. iter ( )
1375
1374
. any ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: NonGlobal ) ) ) ;
1376
1375
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
+ }
1387
1386
}
1388
1387
1389
- if candidates. iter ( ) . any ( |c| matches ! ( c. source, CandidateSource :: AliasBound ) ) {
1388
+ if candidates. applicable . iter ( ) . any ( |c| matches ! ( c. source, CandidateSource :: AliasBound ) ) {
1390
1389
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 ) )
1394
1392
. 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
+ }
1400
1397
}
1401
1398
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 ) ;
1404
1401
1405
1402
// If there are *only* global where bounds, then make sure to return that this
1406
1403
// is still reported as being proven-via the param-env so that rigid projections
1407
1404
// operate correctly. Otherwise, drop all global where-bounds before merging the
1408
1405
// remaining candidates.
1409
1406
let proven_via = if candidates
1407
+ . applicable
1410
1408
. iter ( )
1411
1409
. all ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) )
1412
1410
{
1413
1411
TraitGoalProvenVia :: ParamEnv
1414
1412
} else {
1415
1413
candidates
1414
+ . applicable
1416
1415
. retain ( |c| !matches ! ( c. source, CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) ) ;
1417
1416
TraitGoalProvenVia :: Misc
1418
1417
} ;
1419
1418
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 ) ) ,
1425
1422
}
1426
1423
}
1427
1424
0 commit comments