aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-05-15 19:28:07 +0100
committerFlorian Diebold <[email protected]>2021-05-21 16:48:34 +0100
commit8397734cfe26793d3e9f9ec5f8392655a4b8e106 (patch)
tree4ccb4df2b209ea6a50332be32265accaffe08211 /crates
parent48c492af7ec8ff6af4fe2b38f83aa007c9f7f0b8 (diff)
Fix HIR expecting errors to unify with anything
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs9
-rw-r--r--crates/hir_ty/src/infer/unify.rs8
-rw-r--r--crates/hir_ty/src/lib.rs56
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
89pub fn could_unify(db: &dyn HirDatabase, env: Arc<TraitEnvironment>, t1: &Ty, t2: &Ty) -> bool { 89pub 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
93pub(crate) fn unify( 97pub(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};
46use stdx::always;
46 47
47use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 48use 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
331pub fn replace_errors_with_variables<T>(t: T) -> Canonical<T::Result>
332where
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}