]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-engine/src/slg.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / chalk-engine / src / slg.rs
CommitLineData
5869c6ff 1use crate::ExClause;
1b1a35ee 2
f035d41b 3use chalk_derive::HasInterner;
f035d41b
XL
4use chalk_ir::interner::Interner;
5use chalk_ir::*;
1b1a35ee 6use chalk_solve::infer::InferenceTable;
1b1a35ee
XL
7use chalk_solve::RustIrDatabase;
8
9use std::fmt::Debug;
f035d41b
XL
10use std::marker::PhantomData;
11
12pub(crate) mod aggregate;
13mod resolvent;
14
f035d41b
XL
15#[derive(Clone, Debug, HasInterner)]
16pub(crate) struct SlgContext<I: Interner> {
17 phantom: PhantomData<I>,
18}
19
29967ef6
XL
20impl<I: Interner> SlgContext<I> {
21 pub(crate) fn next_subgoal_index(ex_clause: &ExClause<I>) -> usize {
22 // For now, we always pick the last subgoal in the
23 // list.
24 //
25 // FIXME(rust-lang-nursery/chalk#80) -- we should be more
26 // selective. For example, we don't want to pick a
27 // negative literal that will flounder, and we don't want
28 // to pick things like `?T: Sized` if we can help it.
29 ex_clause.subgoals.len() - 1
30 }
31}
f035d41b
XL
32#[derive(Clone, Debug)]
33pub(crate) struct SlgContextOps<'me, I: Interner> {
34 program: &'me dyn RustIrDatabase<I>,
35 max_size: usize,
36 expected_answers: Option<usize>,
37}
38
39impl<I: Interner> SlgContextOps<'_, I> {
1b1a35ee
XL
40 pub(crate) fn new(
41 program: &dyn RustIrDatabase<I>,
f035d41b
XL
42 max_size: usize,
43 expected_answers: Option<usize>,
1b1a35ee 44 ) -> SlgContextOps<'_, I> {
f035d41b
XL
45 SlgContextOps {
46 program,
47 max_size,
48 expected_answers,
49 }
50 }
f035d41b
XL
51
52 fn identity_constrained_subst(
53 &self,
54 goal: &UCanonical<InEnvironment<Goal<I>>>,
55 ) -> Canonical<ConstrainedSubst<I>> {
56 let (mut infer, subst, _) = InferenceTable::from_canonical(
57 self.program.interner(),
58 goal.universes,
5869c6ff 59 goal.canonical.clone(),
f035d41b
XL
60 );
61 infer
62 .canonicalize(
63 self.program.interner(),
5869c6ff 64 ConstrainedSubst {
f035d41b 65 subst,
1b1a35ee 66 constraints: Constraints::empty(self.program.interner()),
f035d41b
XL
67 },
68 )
69 .quantified
70 }
71
29967ef6
XL
72 pub(crate) fn program(&self) -> &dyn RustIrDatabase<I> {
73 self.program
f035d41b
XL
74 }
75
29967ef6
XL
76 pub(crate) fn max_size(&self) -> usize {
77 self.max_size
f035d41b 78 }
29967ef6 79
5869c6ff
XL
80 pub(crate) fn unification_database(&self) -> &dyn UnificationDatabase<I> {
81 self.program.unification_database()
82 }
29967ef6 83}
f035d41b 84
29967ef6
XL
85pub trait ResolventOps<I: Interner> {
86 /// Combines the `goal` (instantiated within `infer`) with the
87 /// given program clause to yield the start of a new strand (a
88 /// canonical ex-clause).
89 ///
90 /// The bindings in `infer` are unaffected by this operation.
91 fn resolvent_clause(
92 &mut self,
5869c6ff 93 ops: &dyn UnificationDatabase<I>,
29967ef6
XL
94 interner: &I,
95 environment: &Environment<I>,
96 goal: &DomainGoal<I>,
97 subst: &Substitution<I>,
98 clause: &ProgramClause<I>,
99 ) -> Fallible<ExClause<I>>;
100
101 fn apply_answer_subst(
102 &mut self,
103 interner: &I,
5869c6ff 104 unification_database: &dyn UnificationDatabase<I>,
29967ef6
XL
105 ex_clause: &mut ExClause<I>,
106 selected_goal: &InEnvironment<Goal<I>>,
107 answer_table_goal: &Canonical<InEnvironment<Goal<I>>>,
5869c6ff 108 canonical_answer_subst: Canonical<AnswerSubst<I>>,
29967ef6
XL
109 ) -> Fallible<()>;
110}
111
f035d41b
XL
112trait SubstitutionExt<I: Interner> {
113 fn may_invalidate(&self, interner: &I, subst: &Canonical<Substitution<I>>) -> bool;
114}
115
116impl<I: Interner> SubstitutionExt<I> for Substitution<I> {
117 fn may_invalidate(&self, interner: &I, subst: &Canonical<Substitution<I>>) -> bool {
118 self.iter(interner)
119 .zip(subst.value.iter(interner))
120 .any(|(new, current)| MayInvalidate { interner }.aggregate_generic_args(new, current))
121 }
122}
123
124// This is a struct in case we need to add state at any point like in AntiUnifier
125struct MayInvalidate<'i, I> {
126 interner: &'i I,
127}
128
129impl<I: Interner> MayInvalidate<'_, I> {
130 fn aggregate_generic_args(&mut self, new: &GenericArg<I>, current: &GenericArg<I>) -> bool {
131 let interner = self.interner;
132 match (new.data(interner), current.data(interner)) {
133 (GenericArgData::Ty(ty1), GenericArgData::Ty(ty2)) => self.aggregate_tys(ty1, ty2),
134 (GenericArgData::Lifetime(l1), GenericArgData::Lifetime(l2)) => {
135 self.aggregate_lifetimes(l1, l2)
136 }
137 (GenericArgData::Const(c1), GenericArgData::Const(c2)) => self.aggregate_consts(c1, c2),
138 (GenericArgData::Ty(_), _)
139 | (GenericArgData::Lifetime(_), _)
140 | (GenericArgData::Const(_), _) => panic!(
141 "mismatched parameter kinds: new={:?} current={:?}",
142 new, current
143 ),
144 }
145 }
146
147 /// Returns true if the two types could be unequal.
148 fn aggregate_tys(&mut self, new: &Ty<I>, current: &Ty<I>) -> bool {
149 let interner = self.interner;
29967ef6
XL
150 match (new.kind(interner), current.kind(interner)) {
151 (_, TyKind::BoundVar(_)) => {
f035d41b
XL
152 // If the aggregate solution already has an inference
153 // variable here, then no matter what type we produce,
154 // the aggregate cannot get 'more generalized' than it
155 // already is. So return false, we cannot invalidate.
156 //
157 // (Note that "inference variables" show up as *bound
158 // variables* here, because we are looking at the
159 // canonical form.)
160 false
161 }
162
29967ef6 163 (TyKind::BoundVar(_), _) => {
f035d41b
XL
164 // If we see a type variable in the potential future
165 // solution, we have to be conservative. We don't know
166 // what type variable will wind up being! Remember
167 // that the future solution could be any instantiation
168 // of `ty0` -- or it could leave this variable
169 // unbound, if the result is true for all types.
170 //
171 // (Note that "inference variables" show up as *bound
172 // variables* here, because we are looking at the
173 // canonical form.)
174 true
175 }
176
29967ef6 177 (TyKind::InferenceVar(_, _), _) | (_, TyKind::InferenceVar(_, _)) => {
f035d41b
XL
178 panic!(
179 "unexpected free inference variable in may-invalidate: {:?} vs {:?}",
180 new, current,
181 );
182 }
183
29967ef6 184 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) => {
f035d41b
XL
185 self.aggregate_placeholders(p1, p2)
186 }
187
188 (
29967ef6
XL
189 TyKind::Alias(AliasTy::Projection(proj1)),
190 TyKind::Alias(AliasTy::Projection(proj2)),
f035d41b
XL
191 ) => self.aggregate_projection_tys(proj1, proj2),
192
193 (
29967ef6
XL
194 TyKind::Alias(AliasTy::Opaque(opaque_ty1)),
195 TyKind::Alias(AliasTy::Opaque(opaque_ty2)),
f035d41b
XL
196 ) => self.aggregate_opaque_ty_tys(opaque_ty1, opaque_ty2),
197
29967ef6
XL
198 (TyKind::Adt(id_a, substitution_a), TyKind::Adt(id_b, substitution_b)) => {
199 self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
200 }
201 (
202 TyKind::AssociatedType(id_a, substitution_a),
203 TyKind::AssociatedType(id_b, substitution_b),
204 ) => self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b),
205 (TyKind::Scalar(scalar_a), TyKind::Scalar(scalar_b)) => scalar_a != scalar_b,
206 (TyKind::Str, TyKind::Str) => false,
207 (TyKind::Tuple(arity_a, substitution_a), TyKind::Tuple(arity_b, substitution_b)) => {
208 self.aggregate_name_and_substs(arity_a, substitution_a, arity_b, substitution_b)
209 }
210 (
211 TyKind::OpaqueType(id_a, substitution_a),
212 TyKind::OpaqueType(id_b, substitution_b),
213 ) => self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b),
214 (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => self.aggregate_tys(ty_a, ty_b),
215 (TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
216 self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
217 }
218 (TyKind::Ref(id_a, lifetime_a, ty_a), TyKind::Ref(id_b, lifetime_b, ty_b)) => {
219 id_a != id_b
220 || self.aggregate_lifetimes(lifetime_a, lifetime_b)
221 || self.aggregate_tys(ty_a, ty_b)
222 }
223 (TyKind::Raw(id_a, ty_a), TyKind::Raw(id_b, ty_b)) => {
224 id_a != id_b || self.aggregate_tys(ty_a, ty_b)
225 }
226 (TyKind::Never, TyKind::Never) => false,
227 (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) => {
228 self.aggregate_tys(ty_a, ty_b) || self.aggregate_consts(const_a, const_b)
229 }
230 (TyKind::Closure(id_a, substitution_a), TyKind::Closure(id_b, substitution_b)) => {
231 self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
232 }
233 (TyKind::Generator(id_a, substitution_a), TyKind::Generator(id_b, substitution_b)) => {
234 self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
235 }
236 (
237 TyKind::GeneratorWitness(id_a, substitution_a),
238 TyKind::GeneratorWitness(id_b, substitution_b),
239 ) => self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b),
240 (TyKind::Foreign(id_a), TyKind::Foreign(id_b)) => id_a != id_b,
241 (TyKind::Error, TyKind::Error) => false,
242
243 (_, _) => true,
f035d41b
XL
244 }
245 }
246
5869c6ff 247 /// Returns true if the two consts could be unequal.
f035d41b
XL
248 fn aggregate_lifetimes(&mut self, _: &Lifetime<I>, _: &Lifetime<I>) -> bool {
249 true
250 }
251
252 /// Returns true if the two consts could be unequal.
253 fn aggregate_consts(&mut self, new: &Const<I>, current: &Const<I>) -> bool {
254 let interner = self.interner;
255 let ConstData {
256 ty: new_ty,
257 value: new_value,
258 } = new.data(interner);
259 let ConstData {
260 ty: current_ty,
261 value: current_value,
262 } = current.data(interner);
263
264 if self.aggregate_tys(new_ty, current_ty) {
265 return true;
266 }
267
268 match (new_value, current_value) {
269 (_, ConstValue::BoundVar(_)) => {
270 // see comment in aggregate_tys
271 false
272 }
273
274 (ConstValue::BoundVar(_), _) => {
275 // see comment in aggregate_tys
276 true
277 }
278
279 (ConstValue::InferenceVar(_), _) | (_, ConstValue::InferenceVar(_)) => {
280 panic!(
281 "unexpected free inference variable in may-invalidate: {:?} vs {:?}",
282 new, current,
283 );
284 }
285
286 (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) => {
287 self.aggregate_placeholders(p1, p2)
288 }
289
290 (ConstValue::Concrete(c1), ConstValue::Concrete(c2)) => {
291 !c1.const_eq(new_ty, c2, interner)
292 }
293
294 // Only variants left are placeholder = concrete, which always fails
295 (ConstValue::Placeholder(_), _) | (ConstValue::Concrete(_), _) => true,
296 }
297 }
298
f035d41b
XL
299 fn aggregate_placeholders(
300 &mut self,
301 new: &PlaceholderIndex,
302 current: &PlaceholderIndex,
303 ) -> bool {
304 new != current
305 }
306
307 fn aggregate_projection_tys(
308 &mut self,
309 new: &ProjectionTy<I>,
310 current: &ProjectionTy<I>,
311 ) -> bool {
312 let ProjectionTy {
313 associated_ty_id: new_name,
314 substitution: new_substitution,
315 } = new;
316 let ProjectionTy {
317 associated_ty_id: current_name,
318 substitution: current_substitution,
319 } = current;
320
321 self.aggregate_name_and_substs(
322 new_name,
323 new_substitution,
324 current_name,
325 current_substitution,
326 )
327 }
328
329 fn aggregate_opaque_ty_tys(&mut self, new: &OpaqueTy<I>, current: &OpaqueTy<I>) -> bool {
330 let OpaqueTy {
331 opaque_ty_id: new_name,
332 substitution: new_substitution,
333 } = new;
334 let OpaqueTy {
335 opaque_ty_id: current_name,
336 substitution: current_substitution,
337 } = current;
338
339 self.aggregate_name_and_substs(
340 new_name,
341 new_substitution,
342 current_name,
343 current_substitution,
344 )
345 }
346
347 fn aggregate_name_and_substs<N>(
348 &mut self,
349 new_name: N,
350 new_substitution: &Substitution<I>,
351 current_name: N,
352 current_substitution: &Substitution<I>,
353 ) -> bool
354 where
355 N: Copy + Eq + Debug,
356 {
357 let interner = self.interner;
358 if new_name != current_name {
359 return true;
360 }
361
362 let name = new_name;
363
364 assert_eq!(
365 new_substitution.len(interner),
366 current_substitution.len(interner),
367 "does {:?} take {} substitution or {}? can't both be right",
368 name,
369 new_substitution.len(interner),
370 current_substitution.len(interner)
371 );
372
373 new_substitution
374 .iter(interner)
375 .zip(current_substitution.iter(interner))
376 .any(|(new, current)| self.aggregate_generic_args(new, current))
377 }
378}