diff options
-rw-r--r-- | crates/hir/src/lib.rs | 9 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 8 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 56 |
3 files changed, 65 insertions, 8 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 21b1a8e4a..1429384cb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -2051,11 +2051,7 @@ impl Type { | |||
2051 | name: Option<&Name>, | 2051 | name: Option<&Name>, |
2052 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 2052 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
2053 | ) -> Option<T> { | 2053 | ) -> Option<T> { |
2054 | // There should be no inference vars in types passed here | 2054 | let canonical = hir_ty::replace_errors_with_variables(self.ty.clone()); |
2055 | // FIXME check that? | ||
2056 | // FIXME replace Unknown by bound vars here | ||
2057 | let canonical = | ||
2058 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
2059 | 2055 | ||
2060 | let env = self.env.clone(); | 2056 | let env = self.env.clone(); |
2061 | let krate = krate.id; | 2057 | let krate = krate.id; |
@@ -2224,7 +2220,8 @@ impl Type { | |||
2224 | } | 2220 | } |
2225 | 2221 | ||
2226 | pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool { | 2222 | pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool { |
2227 | could_unify(db, self.env.clone(), &self.ty, &other.ty) | 2223 | let tys = hir_ty::replace_errors_with_variables((self.ty.clone(), other.ty.clone())); |
2224 | could_unify(db, self.env.clone(), &tys) | ||
2228 | } | 2225 | } |
2229 | } | 2226 | } |
2230 | 2227 | ||
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 56e06b7d0..d8edfb4e9 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -86,8 +86,12 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> { | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | pub fn could_unify(db: &dyn HirDatabase, env: Arc<TraitEnvironment>, t1: &Ty, t2: &Ty) -> bool { | 89 | pub fn could_unify( |
90 | InferenceTable::new(db, env).unify(t1, t2) | 90 | db: &dyn HirDatabase, |
91 | env: Arc<TraitEnvironment>, | ||
92 | tys: &Canonical<(Ty, Ty)>, | ||
93 | ) -> bool { | ||
94 | unify(db, env, tys).is_some() | ||
91 | } | 95 | } |
92 | 96 | ||
93 | pub(crate) fn unify( | 97 | pub(crate) fn unify( |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 06d5cd0b6..56f60c46b 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -43,6 +43,7 @@ use hir_def::{ | |||
43 | type_ref::{ConstScalar, Rawness}, | 43 | type_ref::{ConstScalar, Rawness}, |
44 | TypeParamId, | 44 | TypeParamId, |
45 | }; | 45 | }; |
46 | use stdx::always; | ||
46 | 47 | ||
47 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; | 48 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; |
48 | 49 | ||
@@ -326,3 +327,58 @@ pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>( | |||
326 | } | 327 | } |
327 | t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") | 328 | t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") |
328 | } | 329 | } |
330 | |||
331 | pub fn replace_errors_with_variables<T>(t: T) -> Canonical<T::Result> | ||
332 | where | ||
333 | T: HasInterner<Interner = Interner> + Fold<Interner>, | ||
334 | T::Result: HasInterner<Interner = Interner>, | ||
335 | { | ||
336 | use chalk_ir::{ | ||
337 | fold::{Folder, SuperFold}, | ||
338 | Fallible, | ||
339 | }; | ||
340 | struct ErrorReplacer { | ||
341 | vars: usize, | ||
342 | } | ||
343 | impl<'i> Folder<'i, Interner> for ErrorReplacer { | ||
344 | fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> { | ||
345 | self | ||
346 | } | ||
347 | |||
348 | fn interner(&self) -> &'i Interner { | ||
349 | &Interner | ||
350 | } | ||
351 | |||
352 | fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> { | ||
353 | if let TyKind::Error = ty.kind(&Interner) { | ||
354 | let index = self.vars; | ||
355 | self.vars += 1; | ||
356 | Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(&Interner)) | ||
357 | } else { | ||
358 | let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?; | ||
359 | Ok(ty) | ||
360 | } | ||
361 | } | ||
362 | |||
363 | fn fold_inference_ty( | ||
364 | &mut self, | ||
365 | var: InferenceVar, | ||
366 | kind: TyVariableKind, | ||
367 | _outer_binder: DebruijnIndex, | ||
368 | ) -> Fallible<Ty> { | ||
369 | always!(false); | ||
370 | Ok(TyKind::InferenceVar(var, kind).intern(&Interner)) | ||
371 | } | ||
372 | } | ||
373 | let mut error_replacer = ErrorReplacer { vars: 0 }; | ||
374 | let value = t | ||
375 | .fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) | ||
376 | .expect("fold failed unexpectedly"); | ||
377 | let kinds = (0..error_replacer.vars).map(|_| { | ||
378 | chalk_ir::CanonicalVarKind::new( | ||
379 | chalk_ir::VariableKind::Ty(TyVariableKind::General), | ||
380 | chalk_ir::UniverseIndex::ROOT, | ||
381 | ) | ||
382 | }); | ||
383 | Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | ||
384 | } | ||