aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-05-04 17:25:07 +0100
committerFlorian Diebold <[email protected]>2019-05-04 17:25:36 +0100
commitf43e69a64eea0caf8b9f5ced31e7f77dc0d33d65 (patch)
tree08a4e6edf39302e086fe6495fee4de1545e1f8f0 /crates/ra_hir/src/ty
parent5795d773dbcce67577851da02e4d659f0daf1a12 (diff)
Handle recursive types in canonicalization
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs16
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs2
2 files changed, 14 insertions, 4 deletions
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index c9c8959c4..8ca7e957d 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -9,7 +9,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
9 where 9 where
10 'a: 'b, 10 'a: 'b,
11 { 11 {
12 Canonicalizer { ctx: self, free_vars: Vec::new() } 12 Canonicalizer { ctx: self, free_vars: Vec::new(), var_stack: Vec::new() }
13 } 13 }
14} 14}
15 15
@@ -19,6 +19,10 @@ where
19{ 19{
20 ctx: &'b mut InferenceContext<'a, D>, 20 ctx: &'b mut InferenceContext<'a, D>,
21 free_vars: Vec<InferTy>, 21 free_vars: Vec<InferTy>,
22 /// A stack of type variables that is used to detect recursive types (which
23 /// are an error, but we need to protect against them to avoid stack
24 /// overflows).
25 var_stack: Vec<super::TypeVarId>,
22} 26}
23 27
24pub(super) struct Canonicalized<T> { 28pub(super) struct Canonicalized<T> {
@@ -42,9 +46,15 @@ where
42 ty.fold(&mut |ty| match ty { 46 ty.fold(&mut |ty| match ty {
43 Ty::Infer(tv) => { 47 Ty::Infer(tv) => {
44 let inner = tv.to_inner(); 48 let inner = tv.to_inner();
45 // TODO prevent infinite loops? => keep var stack 49 if self.var_stack.contains(&inner) {
50 // recursive type
51 return tv.fallback_value();
52 }
46 if let Some(known_ty) = self.ctx.var_unification_table.probe_value(inner).known() { 53 if let Some(known_ty) = self.ctx.var_unification_table.probe_value(inner).known() {
47 self.do_canonicalize_ty(known_ty.clone()) 54 self.var_stack.push(inner);
55 let result = self.do_canonicalize_ty(known_ty.clone());
56 self.var_stack.pop();
57 result
48 } else { 58 } else {
49 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner)); 59 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner));
50 let position = self.add(free_var); 60 let position = self.add(free_var);
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 0c6e5a4f5..74370bae9 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -183,7 +183,7 @@ where
183 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { 183 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
184 debug!("struct_datum {:?}", struct_id); 184 debug!("struct_datum {:?}", struct_id);
185 let type_ctor = from_chalk(self.db, struct_id); 185 let type_ctor = from_chalk(self.db, struct_id);
186 // TODO might be nicer if we can create a fake GenericParams for the TypeCtor 186 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
187 let (num_params, upstream) = match type_ctor { 187 let (num_params, upstream) = match type_ctor {
188 TypeCtor::Bool 188 TypeCtor::Bool
189 | TypeCtor::Char 189 | TypeCtor::Char