Handle recursive types in canonicalization

This commit is contained in:
Florian Diebold 2019-05-04 18:25:07 +02:00
parent 5795d773db
commit f43e69a64e
3 changed files with 15 additions and 5 deletions

View File

@ -351,7 +351,7 @@ impl SourceAnalyzer {
callback: impl FnMut(&Ty, Function) -> Option<T>,
) -> Option<T> {
// There should be no inference vars in types passed here
// TODO check that?
// FIXME check that?
let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
crate::ty::method_resolution::iterate_method_candidates(
&canonical,

View File

@ -9,7 +9,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
where
'a: 'b,
{
Canonicalizer { ctx: self, free_vars: Vec::new() }
Canonicalizer { ctx: self, free_vars: Vec::new(), var_stack: Vec::new() }
}
}
@ -19,6 +19,10 @@ where
{
ctx: &'b mut InferenceContext<'a, D>,
free_vars: Vec<InferTy>,
/// A stack of type variables that is used to detect recursive types (which
/// are an error, but we need to protect against them to avoid stack
/// overflows).
var_stack: Vec<super::TypeVarId>,
}
pub(super) struct Canonicalized<T> {
@ -42,9 +46,15 @@ where
ty.fold(&mut |ty| match ty {
Ty::Infer(tv) => {
let inner = tv.to_inner();
// TODO prevent infinite loops? => keep var stack
if self.var_stack.contains(&inner) {
// recursive type
return tv.fallback_value();
}
if let Some(known_ty) = self.ctx.var_unification_table.probe_value(inner).known() {
self.do_canonicalize_ty(known_ty.clone())
self.var_stack.push(inner);
let result = self.do_canonicalize_ty(known_ty.clone());
self.var_stack.pop();
result
} else {
let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner));
let position = self.add(free_var);

View File

@ -183,7 +183,7 @@ where
fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
debug!("struct_datum {:?}", struct_id);
let type_ctor = from_chalk(self.db, struct_id);
// TODO might be nicer if we can create a fake GenericParams for the TypeCtor
// FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
let (num_params, upstream) = match type_ctor {
TypeCtor::Bool
| TypeCtor::Char