@@ -11,6 +11,7 @@ use rustc_type_ir::visit::TypeVisitableExt as _;
11
11
use rustc_type_ir:: { self as ty, Interner , TypingMode , Upcast as _, elaborate} ;
12
12
use tracing:: { debug, instrument} ;
13
13
14
+ use super :: trait_goals:: ProvenVia ;
14
15
use crate :: delegate:: SolverDelegate ;
15
16
use crate :: solve:: inspect:: ProbeKind ;
16
17
use crate :: solve:: {
@@ -337,15 +338,6 @@ where
337
338
338
339
self . assemble_param_env_candidates ( goal, & mut candidates) ;
339
340
340
- match self . typing_mode ( ) {
341
- TypingMode :: Coherence => { }
342
- TypingMode :: Analysis { .. }
343
- | TypingMode :: PostBorrowckAnalysis { .. }
344
- | TypingMode :: PostAnalysis => {
345
- self . discard_impls_shadowed_by_env ( goal, & mut candidates) ;
346
- }
347
- }
348
-
349
341
candidates
350
342
}
351
343
@@ -500,7 +492,7 @@ where
500
492
goal : Goal < I , G > ,
501
493
candidates : & mut Vec < Candidate < I > > ,
502
494
) {
503
- for ( i, assumption) in goal. param_env . caller_bounds ( ) . into_iter ( ) . enumerate ( ) {
495
+ for ( i, assumption) in goal. param_env . caller_bounds ( ) . iter ( ) . enumerate ( ) {
504
496
candidates. extend ( G :: probe_and_consider_implied_clause (
505
497
self ,
506
498
CandidateSource :: ParamEnv ( i) ,
@@ -733,72 +725,38 @@ where
733
725
} )
734
726
}
735
727
736
- /// If there's a where-bound for the current goal, do not use any impl candidates
737
- /// to prove the current goal. Most importantly, if there is a where-bound which does
738
- /// not specify any associated types, we do not allow normalizing the associated type
739
- /// by using an impl, even if it would apply.
740
- ///
741
- /// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/76>
742
- // FIXME(@lcnr): The current structure here makes me unhappy and feels ugly. idk how
743
- // to improve this however. However, this should make it fairly straightforward to refine
744
- // the filtering going forward, so it seems alright-ish for now.
745
- #[ instrument( level = "debug" , skip( self , goal) ) ]
746
- fn discard_impls_shadowed_by_env < G : GoalKind < D > > (
728
+ // TODO comments
729
+ #[ instrument( level = "debug" , skip( self ) , ret) ]
730
+ pub ( super ) fn merge_candidates (
747
731
& mut self ,
748
- goal : Goal < I , G > ,
749
- candidates : & mut Vec < Candidate < I > > ,
750
- ) {
751
- let cx = self . cx ( ) ;
752
- let trait_goal: Goal < I , ty:: TraitPredicate < I > > =
753
- goal. with ( cx, goal. predicate . trait_ref ( cx) ) ;
754
-
755
- let mut trait_candidates_from_env = vec ! [ ] ;
756
- self . probe ( |_| ProbeKind :: ShadowedEnvProbing ) . enter ( |ecx| {
757
- ecx. assemble_param_env_candidates ( trait_goal, & mut trait_candidates_from_env) ;
758
- ecx. assemble_alias_bound_candidates ( trait_goal, & mut trait_candidates_from_env) ;
759
- } ) ;
732
+ proven_via : Option < ProvenVia > ,
733
+ candidates : Vec < Candidate < I > > ,
734
+ ) -> QueryResult < I > {
735
+ let Some ( proven_via) = proven_via else {
736
+ // We don't care about overflow. If proving the trait goal overflowed, then
737
+ // it's enough to report an overflow error for that, we don't also have to
738
+ // overflow during normalization.
739
+ return Ok ( self . make_ambiguous_response_no_constraints ( MaybeCause :: Ambiguity ) ) ;
740
+ } ;
760
741
761
- if !trait_candidates_from_env. is_empty ( ) {
762
- let trait_env_result = self . merge_candidates ( trait_candidates_from_env) ;
763
- match trait_env_result. unwrap ( ) . value . certainty {
764
- // If proving the trait goal succeeds by using the env,
765
- // we freely drop all impl candidates.
766
- //
767
- // FIXME(@lcnr): It feels like this could easily hide
768
- // a forced ambiguity candidate added earlier.
769
- // This feels dangerous.
770
- Certainty :: Yes => {
771
- candidates. retain ( |c| match c. source {
772
- CandidateSource :: Impl ( _) | CandidateSource :: BuiltinImpl ( _) => {
773
- debug ! ( ?c, "discard impl candidate" ) ;
774
- false
775
- }
776
- CandidateSource :: ParamEnv ( _) | CandidateSource :: AliasBound => true ,
777
- CandidateSource :: CoherenceUnknowable => panic ! ( "uh oh" ) ,
778
- } ) ;
779
- }
780
- // If it is still ambiguous we instead just force the whole goal
781
- // to be ambig and wait for inference constraints. See
782
- // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs
783
- Certainty :: Maybe ( cause) => {
784
- debug ! ( ?cause, "force ambiguity" ) ;
785
- * candidates = self . forced_ambiguity ( cause) . into_iter ( ) . collect ( ) ;
786
- }
787
- }
788
- }
789
- }
742
+ let responses: Vec < _ > = match proven_via {
743
+ // Even when a trait bound has been proven using a where-bound, we
744
+ // still need to consider alias-bounds for normalization, see
745
+ // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
746
+ //
747
+ // FIXME(const_trait_impl): should this behavior also be used by
748
+ // constness checking. Doing so is *at least theoretically* breaking,
749
+ // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
750
+ ProvenVia :: ParamEnv | ProvenVia :: AliasBound => candidates
751
+ . iter ( )
752
+ . filter ( |c| {
753
+ matches ! ( c. source, CandidateSource :: AliasBound | CandidateSource :: ParamEnv ( _) )
754
+ } )
755
+ . map ( |c| c. result )
756
+ . collect ( ) ,
757
+ ProvenVia :: Impl => candidates. iter ( ) . map ( |c| c. result ) . collect ( ) ,
758
+ } ;
790
759
791
- /// If there are multiple ways to prove a trait or projection goal, we have
792
- /// to somehow try to merge the candidates into one. If that fails, we return
793
- /// ambiguity.
794
- #[ instrument( level = "debug" , skip( self ) , ret) ]
795
- pub ( super ) fn merge_candidates ( & mut self , candidates : Vec < Candidate < I > > ) -> QueryResult < I > {
796
- // First try merging all candidates. This is complete and fully sound.
797
- let responses = candidates. iter ( ) . map ( |c| c. result ) . collect :: < Vec < _ > > ( ) ;
798
- if let Some ( result) = self . try_merge_responses ( & responses) {
799
- return Ok ( result) ;
800
- } else {
801
- self . flounder ( & responses)
802
- }
760
+ self . try_merge_responses ( & responses) . map_or_else ( || self . flounder ( & responses) , Ok )
803
761
}
804
762
}
0 commit comments