• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Unification and canonicalization logic.
2 
3 use std::{fmt, iter, mem};
4 
5 use chalk_ir::{
6     cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy,
7     IntTy, TyVariableKind, UniverseIndex,
8 };
9 use chalk_solve::infer::ParameterEnaVariableExt;
10 use either::Either;
11 use ena::unify::UnifyKey;
12 use hir_expand::name;
13 use stdx::never;
14 use triomphe::Arc;
15 
16 use super::{InferOk, InferResult, InferenceContext, TypeError};
17 use crate::{
18     consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
19     to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
20     DebruijnIndex, GenericArg, GenericArgData, Goal, Guidance, InEnvironment, InferenceVar,
21     Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution,
22     TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
23 };
24 
25 impl<'a> InferenceContext<'a> {
canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>( &mut self, t: T, ) -> Canonicalized<T> where T: HasInterner<Interner = Interner>,26     pub(super) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
27         &mut self,
28         t: T,
29     ) -> Canonicalized<T>
30     where
31         T: HasInterner<Interner = Interner>,
32     {
33         self.table.canonicalize(t)
34     }
35 }
36 
37 #[derive(Debug, Clone)]
38 pub(crate) struct Canonicalized<T>
39 where
40     T: HasInterner<Interner = Interner>,
41 {
42     pub(crate) value: Canonical<T>,
43     free_vars: Vec<GenericArg>,
44 }
45 
46 impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
apply_solution( &self, ctx: &mut InferenceTable<'_>, solution: Canonical<Substitution>, )47     pub(super) fn apply_solution(
48         &self,
49         ctx: &mut InferenceTable<'_>,
50         solution: Canonical<Substitution>,
51     ) {
52         // the solution may contain new variables, which we need to convert to new inference vars
53         let new_vars = Substitution::from_iter(
54             Interner,
55             solution.binders.iter(Interner).map(|k| match &k.kind {
56                 VariableKind::Ty(TyVariableKind::General) => ctx.new_type_var().cast(Interner),
57                 VariableKind::Ty(TyVariableKind::Integer) => ctx.new_integer_var().cast(Interner),
58                 VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner),
59                 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
60                 VariableKind::Lifetime => static_lifetime().cast(Interner),
61                 VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner),
62             }),
63         );
64         for (i, v) in solution.value.iter(Interner).enumerate() {
65             let var = self.free_vars[i].clone();
66             if let Some(ty) = v.ty(Interner) {
67                 // eagerly replace projections in the type; we may be getting types
68                 // e.g. from where clauses where this hasn't happened yet
69                 let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), Interner));
70                 ctx.unify(var.assert_ty_ref(Interner), &ty);
71             } else {
72                 let _ = ctx.try_unify(&var, &new_vars.apply(v.clone(), Interner));
73             }
74         }
75     }
76 }
77 
could_unify( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, tys: &Canonical<(Ty, Ty)>, ) -> bool78 pub fn could_unify(
79     db: &dyn HirDatabase,
80     env: Arc<TraitEnvironment>,
81     tys: &Canonical<(Ty, Ty)>,
82 ) -> bool {
83     unify(db, env, tys).is_some()
84 }
85 
unify( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, tys: &Canonical<(Ty, Ty)>, ) -> Option<Substitution>86 pub(crate) fn unify(
87     db: &dyn HirDatabase,
88     env: Arc<TraitEnvironment>,
89     tys: &Canonical<(Ty, Ty)>,
90 ) -> Option<Substitution> {
91     let mut table = InferenceTable::new(db, env);
92     let vars = Substitution::from_iter(
93         Interner,
94         tys.binders.iter(Interner).map(|x| match &x.kind {
95             chalk_ir::VariableKind::Ty(_) => {
96                 GenericArgData::Ty(table.new_type_var()).intern(Interner)
97             }
98             chalk_ir::VariableKind::Lifetime => {
99                 GenericArgData::Ty(table.new_type_var()).intern(Interner)
100             } // FIXME: maybe wrong?
101             chalk_ir::VariableKind::Const(ty) => {
102                 GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
103             }
104         }),
105     );
106     let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
107     let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
108     if !table.unify(&ty1_with_vars, &ty2_with_vars) {
109         return None;
110     }
111     // default any type vars that weren't unified back to their original bound vars
112     // (kind of hacky)
113     let find_var = |iv| {
114         vars.iter(Interner).position(|v| match v.interned() {
115             chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
116             chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
117             chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
118         } == Some(iv))
119     };
120     let fallback = |iv, kind, default, binder| match kind {
121         chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
122             .map_or(default, |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner)),
123         chalk_ir::VariableKind::Lifetime => find_var(iv)
124             .map_or(default, |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner)),
125         chalk_ir::VariableKind::Const(ty) => find_var(iv)
126             .map_or(default, |i| BoundVar::new(binder, i).to_const(Interner, ty).cast(Interner)),
127     };
128     Some(Substitution::from_iter(
129         Interner,
130         vars.iter(Interner).map(|v| table.resolve_with_fallback(v.clone(), &fallback)),
131     ))
132 }
133 
134 bitflags::bitflags! {
135     #[derive(Default, Clone, Copy)]
136     pub(crate) struct TypeVariableFlags: u8 {
137         const DIVERGING = 1 << 0;
138         const INTEGER = 1 << 1;
139         const FLOAT = 1 << 2;
140     }
141 }
142 
143 type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
144 
145 #[derive(Clone)]
146 pub(crate) struct InferenceTable<'a> {
147     pub(crate) db: &'a dyn HirDatabase,
148     pub(crate) trait_env: Arc<TraitEnvironment>,
149     var_unification_table: ChalkInferenceTable,
150     type_variable_table: Vec<TypeVariableFlags>,
151     pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
152 }
153 
154 pub(crate) struct InferenceTableSnapshot {
155     var_table_snapshot: chalk_solve::infer::InferenceSnapshot<Interner>,
156     pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
157     type_variable_table_snapshot: Vec<TypeVariableFlags>,
158 }
159 
160 impl<'a> InferenceTable<'a> {
new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self161     pub(crate) fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self {
162         InferenceTable {
163             db,
164             trait_env,
165             var_unification_table: ChalkInferenceTable::new(),
166             type_variable_table: Vec::new(),
167             pending_obligations: Vec::new(),
168         }
169     }
170 
171     /// Chalk doesn't know about the `diverging` flag, so when it unifies two
172     /// type variables of which one is diverging, the chosen root might not be
173     /// diverging and we have no way of marking it as such at that time. This
174     /// function goes through all type variables and make sure their root is
175     /// marked as diverging if necessary, so that resolving them gives the right
176     /// result.
propagate_diverging_flag(&mut self)177     pub(super) fn propagate_diverging_flag(&mut self) {
178         for i in 0..self.type_variable_table.len() {
179             if !self.type_variable_table[i].contains(TypeVariableFlags::DIVERGING) {
180                 continue;
181             }
182             let v = InferenceVar::from(i as u32);
183             let root = self.var_unification_table.inference_var_root(v);
184             if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
185                 *data |= TypeVariableFlags::DIVERGING;
186             }
187         }
188     }
189 
set_diverging(&mut self, iv: InferenceVar, diverging: bool)190     pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
191         self.type_variable_table[iv.index() as usize].set(TypeVariableFlags::DIVERGING, diverging);
192     }
193 
fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty194     fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
195         match kind {
196             _ if self
197                 .type_variable_table
198                 .get(iv.index() as usize)
199                 .map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)) =>
200             {
201                 TyKind::Never
202             }
203             TyVariableKind::General => TyKind::Error,
204             TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
205             TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
206         }
207         .intern(Interner)
208     }
209 
canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>( &mut self, t: T, ) -> Canonicalized<T> where T: HasInterner<Interner = Interner>,210     pub(crate) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
211         &mut self,
212         t: T,
213     ) -> Canonicalized<T>
214     where
215         T: HasInterner<Interner = Interner>,
216     {
217         // try to resolve obligations before canonicalizing, since this might
218         // result in new knowledge about variables
219         self.resolve_obligations_as_possible();
220         let result = self.var_unification_table.canonicalize(Interner, t);
221         let free_vars = result
222             .free_vars
223             .into_iter()
224             .map(|free_var| free_var.to_generic_arg(Interner))
225             .collect();
226         Canonicalized { value: result.quantified, free_vars }
227     }
228 
229     /// Recurses through the given type, normalizing associated types mentioned
230     /// in it by replacing them by type variables and registering obligations to
231     /// resolve later. This should be done once for every type we get from some
232     /// type annotation (e.g. from a let type annotation, field type or function
233     /// call). `make_ty` handles this already, but e.g. for field types we need
234     /// to do it as well.
normalize_associated_types_in<T>(&mut self, ty: T) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,235     pub(crate) fn normalize_associated_types_in<T>(&mut self, ty: T) -> T
236     where
237         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
238     {
239         fold_tys_and_consts(
240             ty,
241             |e, _| match e {
242                 Either::Left(ty) => Either::Left(match ty.kind(Interner) {
243                     TyKind::Alias(AliasTy::Projection(proj_ty)) => {
244                         self.normalize_projection_ty(proj_ty.clone())
245                     }
246                     _ => ty,
247                 }),
248                 Either::Right(c) => Either::Right(match &c.data(Interner).value {
249                     chalk_ir::ConstValue::Concrete(cc) => match &cc.interned {
250                         crate::ConstScalar::UnevaluatedConst(c_id, subst) => {
251                             // FIXME: Ideally here we should do everything that we do with type alias, i.e. adding a variable
252                             // and registering an obligation. But it needs chalk support, so we handle the most basic
253                             // case (a non associated const without generic parameters) manually.
254                             if subst.len(Interner) == 0 {
255                                 if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone())
256                                 {
257                                     eval
258                                 } else {
259                                     unknown_const(c.data(Interner).ty.clone())
260                                 }
261                             } else {
262                                 unknown_const(c.data(Interner).ty.clone())
263                             }
264                         }
265                         _ => c,
266                     },
267                     _ => c,
268                 }),
269             },
270             DebruijnIndex::INNERMOST,
271         )
272     }
273 
normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty274     pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
275         let var = self.new_type_var();
276         let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
277         let obligation = alias_eq.cast(Interner);
278         self.register_obligation(obligation);
279         var
280     }
281 
extend_type_variable_table(&mut self, to_index: usize)282     fn extend_type_variable_table(&mut self, to_index: usize) {
283         let count = to_index - self.type_variable_table.len() + 1;
284         self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count));
285     }
286 
new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty287     fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
288         let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
289         // Chalk might have created some type variables for its own purposes that we don't know about...
290         self.extend_type_variable_table(var.index() as usize);
291         assert_eq!(var.index() as usize, self.type_variable_table.len() - 1);
292         let flags = self.type_variable_table.get_mut(var.index() as usize).unwrap();
293         if diverging {
294             *flags |= TypeVariableFlags::DIVERGING;
295         }
296         if matches!(kind, TyVariableKind::Integer) {
297             *flags |= TypeVariableFlags::INTEGER;
298         } else if matches!(kind, TyVariableKind::Float) {
299             *flags |= TypeVariableFlags::FLOAT;
300         }
301         var.to_ty_with_kind(Interner, kind)
302     }
303 
new_type_var(&mut self) -> Ty304     pub(crate) fn new_type_var(&mut self) -> Ty {
305         self.new_var(TyVariableKind::General, false)
306     }
307 
new_integer_var(&mut self) -> Ty308     pub(crate) fn new_integer_var(&mut self) -> Ty {
309         self.new_var(TyVariableKind::Integer, false)
310     }
311 
new_float_var(&mut self) -> Ty312     pub(crate) fn new_float_var(&mut self) -> Ty {
313         self.new_var(TyVariableKind::Float, false)
314     }
315 
new_maybe_never_var(&mut self) -> Ty316     pub(crate) fn new_maybe_never_var(&mut self) -> Ty {
317         self.new_var(TyVariableKind::General, true)
318     }
319 
new_const_var(&mut self, ty: Ty) -> Const320     pub(crate) fn new_const_var(&mut self, ty: Ty) -> Const {
321         let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
322         var.to_const(Interner, ty)
323     }
324 
new_lifetime_var(&mut self) -> Lifetime325     pub(crate) fn new_lifetime_var(&mut self) -> Lifetime {
326         let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
327         var.to_lifetime(Interner)
328     }
329 
resolve_with_fallback<T>( &mut self, t: T, fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg, ) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,330     pub(crate) fn resolve_with_fallback<T>(
331         &mut self,
332         t: T,
333         fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
334     ) -> T
335     where
336         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
337     {
338         self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
339     }
340 
fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) -> Substitution341     pub(crate) fn fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) -> Substitution {
342         Substitution::from_iter(
343             Interner,
344             binders.iter().map(|kind| {
345                 let param_infer_var =
346                     kind.map_ref(|&ui| self.var_unification_table.new_variable(ui));
347                 param_infer_var.to_generic_arg(Interner)
348             }),
349         )
350     }
351 
instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug,352     pub(crate) fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T
353     where
354         T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug,
355     {
356         let subst = self.fresh_subst(canonical.binders.as_slice(Interner));
357         subst.apply(canonical.value, Interner)
358     }
359 
resolve_with_fallback_inner<T>( &mut self, var_stack: &mut Vec<InferenceVar>, t: T, fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg, ) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,360     fn resolve_with_fallback_inner<T>(
361         &mut self,
362         var_stack: &mut Vec<InferenceVar>,
363         t: T,
364         fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
365     ) -> T
366     where
367         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
368     {
369         t.fold_with(
370             &mut resolve::Resolver { table: self, var_stack, fallback },
371             DebruijnIndex::INNERMOST,
372         )
373     }
374 
resolve_completely<T>(&mut self, t: T) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,375     pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T
376     where
377         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
378     {
379         self.resolve_with_fallback(t, &|_, _, d, _| d)
380     }
381 
382     /// Apply a fallback to unresolved scalar types. Integer type variables and float type
383     /// variables are replaced with i32 and f64, respectively.
384     ///
385     /// This method is only intended to be called just before returning inference results (i.e. in
386     /// `InferenceContext::resolve_all()`).
387     ///
388     /// FIXME: This method currently doesn't apply fallback to unconstrained general type variables
389     /// whereas rustc replaces them with `()` or `!`.
fallback_if_possible(&mut self)390     pub(super) fn fallback_if_possible(&mut self) {
391         let int_fallback = TyKind::Scalar(Scalar::Int(IntTy::I32)).intern(Interner);
392         let float_fallback = TyKind::Scalar(Scalar::Float(FloatTy::F64)).intern(Interner);
393 
394         let scalar_vars: Vec<_> = self
395             .type_variable_table
396             .iter()
397             .enumerate()
398             .filter_map(|(index, flags)| {
399                 let kind = if flags.contains(TypeVariableFlags::INTEGER) {
400                     TyVariableKind::Integer
401                 } else if flags.contains(TypeVariableFlags::FLOAT) {
402                     TyVariableKind::Float
403                 } else {
404                     return None;
405                 };
406 
407                 // FIXME: This is not really the nicest way to get `InferenceVar`s. Can we get them
408                 // without directly constructing them from `index`?
409                 let var = InferenceVar::from(index as u32).to_ty(Interner, kind);
410                 Some(var)
411             })
412             .collect();
413 
414         for var in scalar_vars {
415             let maybe_resolved = self.resolve_ty_shallow(&var);
416             if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) {
417                 let fallback = match kind {
418                     TyVariableKind::Integer => &int_fallback,
419                     TyVariableKind::Float => &float_fallback,
420                     TyVariableKind::General => unreachable!(),
421                 };
422                 self.unify(&var, fallback);
423             }
424         }
425     }
426 
427     /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
unify<T: ?Sized + Zip<Interner>>(&mut self, ty1: &T, ty2: &T) -> bool428     pub(crate) fn unify<T: ?Sized + Zip<Interner>>(&mut self, ty1: &T, ty2: &T) -> bool {
429         let result = match self.try_unify(ty1, ty2) {
430             Ok(r) => r,
431             Err(_) => return false,
432         };
433         self.register_infer_ok(result);
434         true
435     }
436 
437     /// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the
438     /// caller needs to deal with them.
try_unify<T: ?Sized + Zip<Interner>>( &mut self, t1: &T, t2: &T, ) -> InferResult<()>439     pub(crate) fn try_unify<T: ?Sized + Zip<Interner>>(
440         &mut self,
441         t1: &T,
442         t2: &T,
443     ) -> InferResult<()> {
444         match self.var_unification_table.relate(
445             Interner,
446             &self.db,
447             &self.trait_env.env,
448             chalk_ir::Variance::Invariant,
449             t1,
450             t2,
451         ) {
452             Ok(result) => Ok(InferOk { goals: result.goals, value: () }),
453             Err(chalk_ir::NoSolution) => Err(TypeError),
454         }
455     }
456 
457     /// If `ty` is a type variable with known type, returns that type;
458     /// otherwise, return ty.
resolve_ty_shallow(&mut self, ty: &Ty) -> Ty459     pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
460         self.resolve_obligations_as_possible();
461         self.var_unification_table.normalize_ty_shallow(Interner, ty).unwrap_or_else(|| ty.clone())
462     }
463 
snapshot(&mut self) -> InferenceTableSnapshot464     pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot {
465         let var_table_snapshot = self.var_unification_table.snapshot();
466         let type_variable_table_snapshot = self.type_variable_table.clone();
467         let pending_obligations = self.pending_obligations.clone();
468         InferenceTableSnapshot {
469             var_table_snapshot,
470             pending_obligations,
471             type_variable_table_snapshot,
472         }
473     }
474 
rollback_to(&mut self, snapshot: InferenceTableSnapshot)475     pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) {
476         self.var_unification_table.rollback_to(snapshot.var_table_snapshot);
477         self.type_variable_table = snapshot.type_variable_table_snapshot;
478         self.pending_obligations = snapshot.pending_obligations;
479     }
480 
run_in_snapshot<T>(&mut self, f: impl FnOnce(&mut InferenceTable<'_>) -> T) -> T481     pub(crate) fn run_in_snapshot<T>(&mut self, f: impl FnOnce(&mut InferenceTable<'_>) -> T) -> T {
482         let snapshot = self.snapshot();
483         let result = f(self);
484         self.rollback_to(snapshot);
485         result
486     }
487 
488     /// Checks an obligation without registering it. Useful mostly to check
489     /// whether a trait *might* be implemented before deciding to 'lock in' the
490     /// choice (during e.g. method resolution or deref).
try_obligation(&mut self, goal: Goal) -> Option<Solution>491     pub(crate) fn try_obligation(&mut self, goal: Goal) -> Option<Solution> {
492         let in_env = InEnvironment::new(&self.trait_env.env, goal);
493         let canonicalized = self.canonicalize(in_env);
494         let solution =
495             self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value);
496         solution
497     }
498 
register_obligation(&mut self, goal: Goal)499     pub(crate) fn register_obligation(&mut self, goal: Goal) {
500         let in_env = InEnvironment::new(&self.trait_env.env, goal);
501         self.register_obligation_in_env(in_env)
502     }
503 
register_obligation_in_env(&mut self, goal: InEnvironment<Goal>)504     fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
505         let canonicalized = self.canonicalize(goal);
506         if !self.try_resolve_obligation(&canonicalized) {
507             self.pending_obligations.push(canonicalized);
508         }
509     }
510 
register_infer_ok<T>(&mut self, infer_ok: InferOk<T>)511     pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<T>) {
512         infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal));
513     }
514 
resolve_obligations_as_possible(&mut self)515     pub(crate) fn resolve_obligations_as_possible(&mut self) {
516         let _span = profile::span("resolve_obligations_as_possible");
517         let mut changed = true;
518         let mut obligations = Vec::new();
519         while changed {
520             changed = false;
521             mem::swap(&mut self.pending_obligations, &mut obligations);
522             for canonicalized in obligations.drain(..) {
523                 if !self.check_changed(&canonicalized) {
524                     self.pending_obligations.push(canonicalized);
525                     continue;
526                 }
527                 changed = true;
528                 let uncanonical = chalk_ir::Substitute::apply(
529                     &canonicalized.free_vars,
530                     canonicalized.value.value,
531                     Interner,
532                 );
533                 self.register_obligation_in_env(uncanonical);
534             }
535         }
536     }
537 
fudge_inference<T: TypeFoldable<Interner>>( &mut self, f: impl FnOnce(&mut Self) -> T, ) -> T538     pub(crate) fn fudge_inference<T: TypeFoldable<Interner>>(
539         &mut self,
540         f: impl FnOnce(&mut Self) -> T,
541     ) -> T {
542         use chalk_ir::fold::TypeFolder;
543 
544         #[derive(chalk_derive::FallibleTypeFolder)]
545         #[has_interner(Interner)]
546         struct VarFudger<'a, 'b> {
547             table: &'a mut InferenceTable<'b>,
548             highest_known_var: InferenceVar,
549         }
550         impl<'a, 'b> TypeFolder<Interner> for VarFudger<'a, 'b> {
551             fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
552                 self
553             }
554 
555             fn interner(&self) -> Interner {
556                 Interner
557             }
558 
559             fn fold_inference_ty(
560                 &mut self,
561                 var: chalk_ir::InferenceVar,
562                 kind: TyVariableKind,
563                 _outer_binder: chalk_ir::DebruijnIndex,
564             ) -> chalk_ir::Ty<Interner> {
565                 if var < self.highest_known_var {
566                     var.to_ty(Interner, kind)
567                 } else {
568                     self.table.new_type_var()
569                 }
570             }
571 
572             fn fold_inference_lifetime(
573                 &mut self,
574                 var: chalk_ir::InferenceVar,
575                 _outer_binder: chalk_ir::DebruijnIndex,
576             ) -> chalk_ir::Lifetime<Interner> {
577                 if var < self.highest_known_var {
578                     var.to_lifetime(Interner)
579                 } else {
580                     self.table.new_lifetime_var()
581                 }
582             }
583 
584             fn fold_inference_const(
585                 &mut self,
586                 ty: chalk_ir::Ty<Interner>,
587                 var: chalk_ir::InferenceVar,
588                 _outer_binder: chalk_ir::DebruijnIndex,
589             ) -> chalk_ir::Const<Interner> {
590                 if var < self.highest_known_var {
591                     var.to_const(Interner, ty)
592                 } else {
593                     self.table.new_const_var(ty)
594                 }
595             }
596         }
597 
598         let snapshot = self.snapshot();
599         let highest_known_var = self.new_type_var().inference_var(Interner).expect("inference_var");
600         let result = f(self);
601         self.rollback_to(snapshot);
602         result
603             .fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST)
604     }
605 
606     /// This checks whether any of the free variables in the `canonicalized`
607     /// have changed (either been unified with another variable, or with a
608     /// value). If this is not the case, we don't need to try to solve the goal
609     /// again -- it'll give the same result as last time.
check_changed(&mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>) -> bool610     fn check_changed(&mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>) -> bool {
611         canonicalized.free_vars.iter().any(|var| {
612             let iv = match var.data(Interner) {
613                 chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
614                 chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
615                 chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
616             }
617             .expect("free var is not inference var");
618             if self.var_unification_table.probe_var(iv).is_some() {
619                 return true;
620             }
621             let root = self.var_unification_table.inference_var_root(iv);
622             iv != root
623         })
624     }
625 
try_resolve_obligation( &mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>, ) -> bool626     fn try_resolve_obligation(
627         &mut self,
628         canonicalized: &Canonicalized<InEnvironment<Goal>>,
629     ) -> bool {
630         let solution = self.db.trait_solve(
631             self.trait_env.krate,
632             self.trait_env.block,
633             canonicalized.value.clone(),
634         );
635 
636         match solution {
637             Some(Solution::Unique(canonical_subst)) => {
638                 canonicalized.apply_solution(
639                     self,
640                     Canonical {
641                         binders: canonical_subst.binders,
642                         // FIXME: handle constraints
643                         value: canonical_subst.value.subst,
644                     },
645                 );
646                 true
647             }
648             Some(Solution::Ambig(Guidance::Definite(substs))) => {
649                 canonicalized.apply_solution(self, substs);
650                 false
651             }
652             Some(_) => {
653                 // FIXME use this when trying to resolve everything at the end
654                 false
655             }
656             None => {
657                 // FIXME obligation cannot be fulfilled => diagnostic
658                 true
659             }
660         }
661     }
662 
callable_sig( &mut self, ty: &Ty, num_args: usize, ) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)>663     pub(crate) fn callable_sig(
664         &mut self,
665         ty: &Ty,
666         num_args: usize,
667     ) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
668         match ty.callable_sig(self.db) {
669             Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
670             None => {
671                 let (f, args_ty, return_ty) = self.callable_sig_from_fn_trait(ty, num_args)?;
672                 Some((Some(f), args_ty, return_ty))
673             }
674         }
675     }
676 
callable_sig_from_fn_trait( &mut self, ty: &Ty, num_args: usize, ) -> Option<(FnTrait, Vec<Ty>, Ty)>677     fn callable_sig_from_fn_trait(
678         &mut self,
679         ty: &Ty,
680         num_args: usize,
681     ) -> Option<(FnTrait, Vec<Ty>, Ty)> {
682         let krate = self.trait_env.krate;
683         let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
684         let trait_data = self.db.trait_data(fn_once_trait);
685         let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
686 
687         let mut arg_tys = vec![];
688         let arg_ty = TyBuilder::tuple(num_args)
689             .fill(|x| {
690                 let arg = match x {
691                     ParamKind::Type => self.new_type_var(),
692                     ParamKind::Const(ty) => {
693                         never!("Tuple with const parameter");
694                         return GenericArgData::Const(self.new_const_var(ty.clone()))
695                             .intern(Interner);
696                     }
697                 };
698                 arg_tys.push(arg.clone());
699                 GenericArgData::Ty(arg).intern(Interner)
700             })
701             .build();
702 
703         let projection = {
704             let b = TyBuilder::subst_for_def(self.db, fn_once_trait, None);
705             if b.remaining() != 2 {
706                 return None;
707             }
708             let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
709 
710             TyBuilder::assoc_type_projection(self.db, output_assoc_type, Some(fn_once_subst))
711                 .build()
712         };
713 
714         let trait_env = self.trait_env.env.clone();
715         let mut trait_ref = projection.trait_ref(self.db);
716         let obligation = InEnvironment {
717             goal: trait_ref.clone().cast(Interner),
718             environment: trait_env.clone(),
719         };
720         let canonical = self.canonicalize(obligation.clone());
721         if self
722             .db
723             .trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
724             .is_some()
725         {
726             self.register_obligation(obligation.goal);
727             let return_ty = self.normalize_projection_ty(projection);
728             for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
729                 let fn_x_trait = fn_x.get_id(self.db, krate)?;
730                 trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
731                 let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
732                     goal: trait_ref.clone().cast(Interner),
733                     environment: trait_env.clone(),
734                 };
735                 let canonical = self.canonicalize(obligation.clone());
736                 if self
737                     .db
738                     .trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
739                     .is_some()
740                 {
741                     return Some((fn_x, arg_tys, return_ty));
742                 }
743             }
744             unreachable!("It should at least implement FnOnce at this point");
745         } else {
746             None
747         }
748     }
749 
insert_type_vars<T>(&mut self, ty: T) -> T where T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,750     pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
751     where
752         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
753     {
754         fold_tys_and_consts(
755             ty,
756             |x, _| match x {
757                 Either::Left(ty) => Either::Left(self.insert_type_vars_shallow(ty)),
758                 Either::Right(c) => Either::Right(self.insert_const_vars_shallow(c)),
759             },
760             DebruijnIndex::INNERMOST,
761         )
762     }
763 
764     /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
insert_type_vars_shallow(&mut self, ty: Ty) -> Ty765     pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
766         match ty.kind(Interner) {
767             TyKind::Error => self.new_type_var(),
768             TyKind::InferenceVar(..) => {
769                 let ty_resolved = self.resolve_ty_shallow(&ty);
770                 if ty_resolved.is_unknown() {
771                     self.new_type_var()
772                 } else {
773                     ty
774                 }
775             }
776             _ => ty,
777         }
778     }
779 
780     /// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
insert_const_vars_shallow(&mut self, c: Const) -> Const781     pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const {
782         let data = c.data(Interner);
783         match &data.value {
784             ConstValue::Concrete(cc) => match &cc.interned {
785                 crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
786                 // try to evaluate unevaluated const. Replace with new var if const eval failed.
787                 crate::ConstScalar::UnevaluatedConst(id, subst) => {
788                     if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
789                         eval
790                     } else {
791                         self.new_const_var(data.ty.clone())
792                     }
793                 }
794                 _ => c,
795             },
796             _ => c,
797         }
798     }
799 }
800 
801 impl<'a> fmt::Debug for InferenceTable<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result802     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
803         f.debug_struct("InferenceTable").field("num_vars", &self.type_variable_table.len()).finish()
804     }
805 }
806 
807 mod resolve {
808     use super::InferenceTable;
809     use crate::{
810         ConcreteConst, Const, ConstData, ConstScalar, ConstValue, DebruijnIndex, GenericArg,
811         InferenceVar, Interner, Lifetime, Ty, TyVariableKind, VariableKind,
812     };
813     use chalk_ir::{
814         cast::Cast,
815         fold::{TypeFoldable, TypeFolder},
816     };
817 
818     #[derive(chalk_derive::FallibleTypeFolder)]
819     #[has_interner(Interner)]
820     pub(super) struct Resolver<
821         'a,
822         'b,
823         F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
824     > {
825         pub(super) table: &'a mut InferenceTable<'b>,
826         pub(super) var_stack: &'a mut Vec<InferenceVar>,
827         pub(super) fallback: F,
828     }
829     impl<'a, 'b, F> TypeFolder<Interner> for Resolver<'a, 'b, F>
830     where
831         F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
832     {
as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error>833         fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
834             self
835         }
836 
interner(&self) -> Interner837         fn interner(&self) -> Interner {
838             Interner
839         }
840 
fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, outer_binder: DebruijnIndex, ) -> Ty841         fn fold_inference_ty(
842             &mut self,
843             var: InferenceVar,
844             kind: TyVariableKind,
845             outer_binder: DebruijnIndex,
846         ) -> Ty {
847             let var = self.table.var_unification_table.inference_var_root(var);
848             if self.var_stack.contains(&var) {
849                 // recursive type
850                 let default = self.table.fallback_value(var, kind).cast(Interner);
851                 return (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
852                     .assert_ty_ref(Interner)
853                     .clone();
854             }
855             let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
856                 // known_ty may contain other variables that are known by now
857                 self.var_stack.push(var);
858                 let result = known_ty.fold_with(self, outer_binder);
859                 self.var_stack.pop();
860                 result.assert_ty_ref(Interner).clone()
861             } else {
862                 let default = self.table.fallback_value(var, kind).cast(Interner);
863                 (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
864                     .assert_ty_ref(Interner)
865                     .clone()
866             };
867             result
868         }
869 
fold_inference_const( &mut self, ty: Ty, var: InferenceVar, outer_binder: DebruijnIndex, ) -> Const870         fn fold_inference_const(
871             &mut self,
872             ty: Ty,
873             var: InferenceVar,
874             outer_binder: DebruijnIndex,
875         ) -> Const {
876             let var = self.table.var_unification_table.inference_var_root(var);
877             let default = ConstData {
878                 ty: ty.clone(),
879                 value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }),
880             }
881             .intern(Interner)
882             .cast(Interner);
883             if self.var_stack.contains(&var) {
884                 // recursive
885                 return (self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
886                     .assert_const_ref(Interner)
887                     .clone();
888             }
889             if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
890                 // known_ty may contain other variables that are known by now
891                 self.var_stack.push(var);
892                 let result = known_ty.fold_with(self, outer_binder);
893                 self.var_stack.pop();
894                 result.assert_const_ref(Interner).clone()
895             } else {
896                 (self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
897                     .assert_const_ref(Interner)
898                     .clone()
899             }
900         }
901 
fold_inference_lifetime( &mut self, _var: InferenceVar, _outer_binder: DebruijnIndex, ) -> Lifetime902         fn fold_inference_lifetime(
903             &mut self,
904             _var: InferenceVar,
905             _outer_binder: DebruijnIndex,
906         ) -> Lifetime {
907             // fall back all lifetimes to 'static -- currently we don't deal
908             // with any lifetimes, but we can sometimes get some lifetime
909             // variables through Chalk's unification, and this at least makes
910             // sure we don't leak them outside of inference
911             crate::static_lifetime()
912         }
913     }
914 }
915