11//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
22
3+ use std:: cell:: Cell ;
4+
35use rustc_type_ir:: data_structures:: IndexSet ;
46use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
57use rustc_type_ir:: inherent:: * ;
@@ -14,7 +16,7 @@ use tracing::{debug, instrument, trace};
1416use crate :: delegate:: SolverDelegate ;
1517use crate :: solve:: assembly:: structural_traits:: { self , AsyncCallableRelevantTypes } ;
1618use crate :: solve:: assembly:: { self , AllowInferenceConstraints , AssembleCandidatesFrom , Candidate } ;
17- use crate :: solve:: inspect:: ProbeKind ;
19+ use crate :: solve:: inspect:: { self , ProbeKind } ;
1820use crate :: solve:: {
1921 BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , MaybeCause ,
2022 NoSolution , ParamEnvSource , QueryResult , has_only_region_constraints,
4143 self . def_id ( )
4244 }
4345
46+ fn assemble_param_env_candidates_fast_path (
47+ ecx : & mut EvalCtxt < ' _ , D > ,
48+ goal : Goal < I , Self > ,
49+ ) -> Option < Candidate < I > > {
50+ // This is kind of a mess. We need to detect whether there's an applicable
51+ // `ParamEnv` candidate without fully normalizing other candidates to avoid the
52+ // hang in trait-system-refactor-initiative#210. This currently uses structural
53+ // identity, which means it does not apply if there are normalizeable aliases
54+ // in the environment or if the goal is higher ranked.
55+ //
56+ // We generally need such a fast path if multiple potentially applicable where-bounds
57+ // contain aliases whose normalization tries to apply all these where-bounds yet again.
58+ // This can easily result in exponential blowup.
59+ for assumption in goal. param_env . caller_bounds ( ) . iter ( ) . filter_map ( |c| c. as_trait_clause ( ) )
60+ {
61+ if assumption. no_bound_vars ( ) . is_some_and ( |c| c == goal. predicate ) {
62+ let source = Cell :: new ( CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) ;
63+ let Ok ( candidate) = ecx
64+ . probe ( |result : & QueryResult < I > | inspect:: ProbeKind :: TraitCandidate {
65+ source : source. get ( ) ,
66+ result : * result,
67+ } )
68+ . enter ( |ecx| {
69+ source. set ( ecx. characterize_param_env_assumption (
70+ goal. param_env ,
71+ assumption. upcast ( ecx. cx ( ) ) ,
72+ ) ?) ;
73+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
74+ } )
75+ . map ( |result| Candidate { source : source. get ( ) , result } )
76+ else {
77+ continue ;
78+ } ;
79+ if candidate. source == CandidateSource :: ParamEnv ( ParamEnvSource :: NonGlobal ) {
80+ return Some ( candidate) ;
81+ }
82+ }
83+ }
84+ None
85+ }
86+
4487 fn consider_additional_alias_assumptions (
4588 _ecx : & mut EvalCtxt < ' _ , D > ,
4689 _goal : Goal < I , Self > ,
0 commit comments