Fix HIR expecting errors to unify with anything

This commit is contained in:
Florian Diebold 2021-05-15 20:28:07 +02:00
parent 48c492af7e
commit 8397734cfe
3 changed files with 65 additions and 8 deletions

View File

@ -2051,11 +2051,7 @@ pub fn iterate_path_candidates<T>(
name: Option<&Name>,
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
) -> Option<T> {
// There should be no inference vars in types passed here
// FIXME check that?
// FIXME replace Unknown by bound vars here
let canonical =
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
let canonical = hir_ty::replace_errors_with_variables(self.ty.clone());
let env = self.env.clone();
let krate = krate.id;
@ -2224,7 +2220,8 @@ fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
}
pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
could_unify(db, self.env.clone(), &self.ty, &other.ty)
let tys = hir_ty::replace_errors_with_variables((self.ty.clone(), other.ty.clone()));
could_unify(db, self.env.clone(), &tys)
}
}

View File

@ -86,8 +86,12 @@ pub(super) fn apply_solution(
}
}
pub fn could_unify(db: &dyn HirDatabase, env: Arc<TraitEnvironment>, t1: &Ty, t2: &Ty) -> bool {
InferenceTable::new(db, env).unify(t1, t2)
pub fn could_unify(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment>,
tys: &Canonical<(Ty, Ty)>,
) -> bool {
unify(db, env, tys).is_some()
}
pub(crate) fn unify(

View File

@ -43,6 +43,7 @@ macro_rules! eprintln {
type_ref::{ConstScalar, Rawness},
TypeParamId,
};
use stdx::always;
use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
@ -326,3 +327,58 @@ fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
}
t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
}
pub fn replace_errors_with_variables<T>(t: T) -> Canonical<T::Result>
where
T: HasInterner<Interner = Interner> + Fold<Interner>,
T::Result: HasInterner<Interner = Interner>,
{
use chalk_ir::{
fold::{Folder, SuperFold},
Fallible,
};
struct ErrorReplacer {
vars: usize,
}
impl<'i> Folder<'i, Interner> for ErrorReplacer {
fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
self
}
fn interner(&self) -> &'i Interner {
&Interner
}
fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
if let TyKind::Error = ty.kind(&Interner) {
let index = self.vars;
self.vars += 1;
Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(&Interner))
} else {
let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
Ok(ty)
}
}
fn fold_inference_ty(
&mut self,
var: InferenceVar,
kind: TyVariableKind,
_outer_binder: DebruijnIndex,
) -> Fallible<Ty> {
always!(false);
Ok(TyKind::InferenceVar(var, kind).intern(&Interner))
}
}
let mut error_replacer = ErrorReplacer { vars: 0 };
let value = t
.fold_with(&mut error_replacer, DebruijnIndex::INNERMOST)
.expect("fold failed unexpectedly");
let kinds = (0..error_replacer.vars).map(|_| {
chalk_ir::CanonicalVarKind::new(
chalk_ir::VariableKind::Ty(TyVariableKind::General),
chalk_ir::UniverseIndex::ROOT,
)
});
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
}