|
2 | 2 |
|
3 | 3 | pub(super)mod structural_traits; |
4 | 4 |
|
| 5 | +use std::ops::ControlFlow; |
| 6 | + |
5 | 7 | use derive_where::derive_where; |
6 | 8 | use rustc_type_ir::inherent::*; |
7 | 9 | use rustc_type_ir::lang_items::TraitSolverLangItem; |
8 | 10 | use rustc_type_ir::{ |
9 | | -selfas ty,Interner,TypeFoldable,TypeVisitableExtas _,TypingMode,Upcastas _, elaborate, |
| 11 | +selfas ty,Interner,TypeFoldable,TypeSuperVisitable,TypeVisitable,TypeVisitableExtas _, |
| 12 | +TypeVisitor,TypingMode,Upcastas _, elaborate, |
10 | 13 | }; |
11 | 14 | use tracing::{debug, instrument}; |
12 | 15 |
|
13 | | -usesuper::has_only_region_constraints; |
14 | 16 | usesuper::trait_goals::TraitGoalProvenVia; |
| 17 | +usesuper::{has_only_region_constraints, inspect}; |
15 | 18 | usecrate::delegate::SolverDelegate; |
16 | 19 | usecrate::solve::inspect::ProbeKind; |
17 | 20 | usecrate::solve::{ |
18 | 21 | BuiltinImplSource,CandidateSource,CanonicalResponse,Certainty,EvalCtxt,Goal,GoalSource, |
19 | | -MaybeCause,NoSolution,QueryResult, |
| 22 | +MaybeCause,NoSolution,ParamEnvSource,QueryResult, |
20 | 23 | }; |
21 | 24 |
|
22 | 25 | enumAliasBoundKind{ |
|
49 | 52 |
|
50 | 53 | fntrait_def_id(self,cx:I) -> I::DefId; |
51 | 54 |
|
52 | | -/// Try equating an assumption predicate against a goal's predicate. If it |
53 | | -/// holds, then execute the `then` callback, which should do any additional |
54 | | -/// work, then produce a response (typically by executing |
55 | | -/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). |
56 | | -fnprobe_and_match_goal_against_assumption( |
57 | | -ecx:&mutEvalCtxt<'_,D>, |
58 | | -source:CandidateSource<I>, |
59 | | -goal:Goal<I,Self>, |
60 | | -assumption:I::Clause, |
61 | | -then:implFnOnce(&mutEvalCtxt<'_,D>) -> QueryResult<I>, |
62 | | -) -> Result<Candidate<I>,NoSolution>; |
63 | | - |
64 | 55 | /// Consider a clause, which consists of a "assumption" and some "requirements", |
65 | 56 | /// to satisfy a goal. If the requirements hold, then attempt to satisfy our |
66 | 57 | /// goal by equating it with the assumption. |
@@ -119,6 +110,67 @@ where |
119 | 110 | alias_ty: ty::AliasTy<I>, |
120 | 111 | ) -> Vec<Candidate<I>>; |
121 | 112 |
|
| 113 | +fnprobe_and_consider_param_env_candidate( |
| 114 | +ecx:&mutEvalCtxt<'_,D>, |
| 115 | +goal:Goal<I,Self>, |
| 116 | +assumption:I::Clause, |
| 117 | +) -> Result<Candidate<I>,NoSolution>{ |
| 118 | +Self::fast_reject_assumption(ecx, goal, assumption)?; |
| 119 | + |
| 120 | + ecx.probe(|candidate:&Result<Candidate<I>,NoSolution>| match candidate { |
| 121 | +Ok(candidate) => inspect::ProbeKind::TraitCandidate{ |
| 122 | +source: candidate.source, |
| 123 | +result:Ok(candidate.result), |
| 124 | +}, |
| 125 | +Err(NoSolution) => inspect::ProbeKind::TraitCandidate{ |
| 126 | +source:CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), |
| 127 | +result:Err(NoSolution), |
| 128 | +}, |
| 129 | +}) |
| 130 | +.enter(|ecx| { |
| 131 | +Self::match_assumption(ecx, goal, assumption)?; |
| 132 | +let source = ecx.characterize_param_env_assumption(goal.param_env, assumption)?; |
| 133 | +Ok(Candidate{ |
| 134 | + source, |
| 135 | +result: ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?, |
| 136 | +}) |
| 137 | +}) |
| 138 | +} |
| 139 | + |
| 140 | +/// Try equating an assumption predicate against a goal's predicate. If it |
| 141 | +/// holds, then execute the `then` callback, which should do any additional |
| 142 | +/// work, then produce a response (typically by executing |
| 143 | +/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). |
| 144 | +fnprobe_and_match_goal_against_assumption( |
| 145 | +ecx:&mutEvalCtxt<'_,D>, |
| 146 | +source:CandidateSource<I>, |
| 147 | +goal:Goal<I,Self>, |
| 148 | +assumption:I::Clause, |
| 149 | +then:implFnOnce(&mutEvalCtxt<'_,D>) -> QueryResult<I>, |
| 150 | +) -> Result<Candidate<I>,NoSolution>{ |
| 151 | +Self::fast_reject_assumption(ecx, goal, assumption)?; |
| 152 | + |
| 153 | + ecx.probe_trait_candidate(source).enter(|ecx| { |
| 154 | +Self::match_assumption(ecx, goal, assumption)?; |
| 155 | +then(ecx) |
| 156 | +}) |
| 157 | +} |
| 158 | + |
| 159 | +/// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] |
| 160 | +/// and [`I::DefId`]. |
| 161 | +fnfast_reject_assumption( |
| 162 | +ecx:&mutEvalCtxt<'_,D>, |
| 163 | +goal:Goal<I,Self>, |
| 164 | +assumption:I::Clause, |
| 165 | +) -> Result<(),NoSolution>; |
| 166 | + |
| 167 | +/// Relate the goal and assumption. |
| 168 | +fnmatch_assumption( |
| 169 | +ecx:&mutEvalCtxt<'_,D>, |
| 170 | +goal:Goal<I,Self>, |
| 171 | +assumption:I::Clause, |
| 172 | +) -> Result<(),NoSolution>; |
| 173 | + |
122 | 174 | fnconsider_impl_candidate( |
123 | 175 | ecx:&mutEvalCtxt<'_,D>, |
124 | 176 | goal:Goal<I,Self>, |
@@ -500,14 +552,8 @@ where |
500 | 552 | goal:Goal<I,G>, |
501 | 553 | candidates:&mutVec<Candidate<I>>, |
502 | 554 | ){ |
503 | | -for(i, assumption)in goal.param_env.caller_bounds().iter().enumerate(){ |
504 | | - candidates.extend(G::probe_and_consider_implied_clause( |
505 | | -self, |
506 | | -CandidateSource::ParamEnv(i), |
507 | | - goal, |
508 | | - assumption, |
509 | | -[], |
510 | | -)); |
| 555 | +for assumption in goal.param_env.caller_bounds().iter(){ |
| 556 | + candidates.extend(G::probe_and_consider_param_env_candidate(self, goal, assumption)); |
511 | 557 | } |
512 | 558 | } |
513 | 559 |
|
@@ -943,4 +989,76 @@ where |
943 | 989 | } |
944 | 990 | } |
945 | 991 | } |
| 992 | + |
| 993 | +fncharacterize_param_env_assumption( |
| 994 | +&mutself, |
| 995 | +param_env:I::ParamEnv, |
| 996 | +assumption:I::Clause, |
| 997 | +) -> Result<CandidateSource<I>,NoSolution>{ |
| 998 | +// FIXME: |
| 999 | +if assumption.has_bound_vars(){ |
| 1000 | +returnOk(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)); |
| 1001 | +} |
| 1002 | + |
| 1003 | +match assumption.visit_with(&mutFindParamInClause{ecx:self, param_env }){ |
| 1004 | +ControlFlow::Break(Err(NoSolution)) => Err(NoSolution), |
| 1005 | +ControlFlow::Break(Ok(())) => Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)), |
| 1006 | +ControlFlow::Continue(()) => Ok(CandidateSource::ParamEnv(ParamEnvSource::Global)), |
| 1007 | +} |
| 1008 | +} |
| 1009 | +} |
| 1010 | + |
| 1011 | +structFindParamInClause<'a,'b,D:SolverDelegate<Interner = I>,I:Interner>{ |
| 1012 | +ecx:&'amutEvalCtxt<'b,D>, |
| 1013 | +param_env:I::ParamEnv, |
| 1014 | +} |
| 1015 | + |
| 1016 | +impl<D,I>TypeVisitor<I>forFindParamInClause<'_,'_,D,I> |
| 1017 | +where |
| 1018 | +D:SolverDelegate<Interner = I>, |
| 1019 | +I:Interner, |
| 1020 | +{ |
| 1021 | +typeResult = ControlFlow<Result<(),NoSolution>>; |
| 1022 | + |
| 1023 | +fnvisit_binder<T:TypeFoldable<I>>(&mutself,t:&ty::Binder<I,T>) -> Self::Result{ |
| 1024 | +self.ecx.enter_forall(t.clone(), |ecx, v| { |
| 1025 | + v.visit_with(&mutFindParamInClause{ ecx,param_env:self.param_env}) |
| 1026 | +}) |
| 1027 | +} |
| 1028 | + |
| 1029 | +fnvisit_ty(&mutself,ty:I::Ty) -> Self::Result{ |
| 1030 | +letOk(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty)else{ |
| 1031 | +returnControlFlow::Break(Err(NoSolution)); |
| 1032 | +}; |
| 1033 | +let ty = self.ecx.eager_resolve(ty); |
| 1034 | + |
| 1035 | +iflet ty::Placeholder(_) = ty.kind(){ |
| 1036 | +ControlFlow::Break(Ok(())) |
| 1037 | +}else{ |
| 1038 | + ty.super_visit_with(self) |
| 1039 | +} |
| 1040 | +} |
| 1041 | + |
| 1042 | +fnvisit_const(&mutself,ct:I::Const) -> Self::Result{ |
| 1043 | +letOk(ct) = self.ecx.structurally_normalize_const(self.param_env, ct)else{ |
| 1044 | +returnControlFlow::Break(Err(NoSolution)); |
| 1045 | +}; |
| 1046 | +let ct = self.ecx.eager_resolve(ct); |
| 1047 | + |
| 1048 | +iflet ty::ConstKind::Placeholder(_) = ct.kind(){ |
| 1049 | +ControlFlow::Break(Ok(())) |
| 1050 | +}else{ |
| 1051 | + ct.super_visit_with(self) |
| 1052 | +} |
| 1053 | +} |
| 1054 | + |
| 1055 | +fnvisit_region(&mutself,r:I::Region) -> Self::Result{ |
| 1056 | +match r.kind(){ |
| 1057 | + ty::ReStatic | ty::ReError(_) => ControlFlow::Continue(()), |
| 1058 | + ty::ReVar(_) | ty::RePlaceholder(_) => ControlFlow::Break(Ok(())), |
| 1059 | + ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReBound(..) => { |
| 1060 | +unreachable!() |
| 1061 | +} |
| 1062 | +} |
| 1063 | +} |
946 | 1064 | } |
0 commit comments