aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer/unify.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-05-04 14:42:00 +0100
committerFlorian Diebold <[email protected]>2019-05-04 17:18:30 +0100
commit621864319f8e3149c08d4d0f99b975407ba00ffd (patch)
treecbb6f7a9aa414ec0770556899559e746c740d2c9 /crates/ra_hir/src/ty/infer/unify.rs
parent0bcf47b22b01f66c2f2056f5871e32071ba95b01 (diff)
Make canonicalization API a bit nicer
Diffstat (limited to 'crates/ra_hir/src/ty/infer/unify.rs')
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs56
1 files changed, 40 insertions, 16 deletions
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index 820a64789..c9c8959c4 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -13,14 +13,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
13 } 13 }
14} 14}
15 15
16// TODO improve the interface of this
17
18pub(super) struct Canonicalizer<'a, 'b, D: HirDatabase> 16pub(super) struct Canonicalizer<'a, 'b, D: HirDatabase>
19where 17where
20 'a: 'b, 18 'a: 'b,
21{ 19{
22 pub ctx: &'b mut InferenceContext<'a, D>, 20 ctx: &'b mut InferenceContext<'a, D>,
23 pub free_vars: Vec<InferTy>, 21 free_vars: Vec<InferTy>,
22}
23
24pub(super) struct Canonicalized<T> {
25 pub value: Canonical<T>,
26 free_vars: Vec<InferTy>,
24} 27}
25 28
26impl<'a, 'b, D: HirDatabase> Canonicalizer<'a, 'b, D> 29impl<'a, 'b, D: HirDatabase> Canonicalizer<'a, 'b, D>
@@ -35,13 +38,13 @@ where
35 }) 38 })
36 } 39 }
37 40
38 pub fn canonicalize_ty(&mut self, ty: Ty) -> Canonical<Ty> { 41 fn do_canonicalize_ty(&mut self, ty: Ty) -> Ty {
39 let value = ty.fold(&mut |ty| match ty { 42 ty.fold(&mut |ty| match ty {
40 Ty::Infer(tv) => { 43 Ty::Infer(tv) => {
41 let inner = tv.to_inner(); 44 let inner = tv.to_inner();
42 // TODO prevent infinite loops? => keep var stack 45 // TODO prevent infinite loops? => keep var stack
43 if let Some(known_ty) = self.ctx.var_unification_table.probe_value(inner).known() { 46 if let Some(known_ty) = self.ctx.var_unification_table.probe_value(inner).known() {
44 self.canonicalize_ty(known_ty.clone()).value 47 self.do_canonicalize_ty(known_ty.clone())
45 } else { 48 } else {
46 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner)); 49 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner));
47 let position = self.add(free_var); 50 let position = self.add(free_var);
@@ -49,20 +52,37 @@ where
49 } 52 }
50 } 53 }
51 _ => ty, 54 _ => ty,
52 }); 55 })
53 Canonical { value, num_vars: self.free_vars.len() }
54 } 56 }
55 57
56 pub fn canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> Canonical<TraitRef> { 58 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef {
57 let substs = trait_ref 59 let substs = trait_ref
58 .substs 60 .substs
59 .iter() 61 .iter()
60 .map(|ty| self.canonicalize_ty(ty.clone()).value) 62 .map(|ty| self.do_canonicalize_ty(ty.clone()))
61 .collect::<Vec<_>>(); 63 .collect::<Vec<_>>();
62 let value = TraitRef { trait_: trait_ref.trait_, substs: substs.into() }; 64 TraitRef { trait_: trait_ref.trait_, substs: substs.into() }
63 Canonical { value, num_vars: self.free_vars.len() }
64 } 65 }
65 66
67 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
68 Canonicalized {
69 value: Canonical { value: result, num_vars: self.free_vars.len() },
70 free_vars: self.free_vars,
71 }
72 }
73
74 pub fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
75 let result = self.do_canonicalize_ty(ty);
76 self.into_canonicalized(result)
77 }
78
79 pub fn canonicalize_trait_ref(mut self, trait_ref: TraitRef) -> Canonicalized<TraitRef> {
80 let result = self.do_canonicalize_trait_ref(trait_ref);
81 self.into_canonicalized(result)
82 }
83}
84
85impl<T> Canonicalized<T> {
66 pub fn decanonicalize_ty(&self, ty: Ty) -> Ty { 86 pub fn decanonicalize_ty(&self, ty: Ty) -> Ty {
67 ty.fold(&mut |ty| match ty { 87 ty.fold(&mut |ty| match ty {
68 Ty::Bound(idx) => { 88 Ty::Bound(idx) => {
@@ -76,13 +96,17 @@ where
76 }) 96 })
77 } 97 }
78 98
79 pub fn apply_solution(&mut self, solution: Canonical<Vec<Ty>>) { 99 pub fn apply_solution(
100 &self,
101 ctx: &mut InferenceContext<'_, impl HirDatabase>,
102 solution: Canonical<Vec<Ty>>,
103 ) {
80 // the solution may contain new variables, which we need to convert to new inference vars 104 // the solution may contain new variables, which we need to convert to new inference vars
81 let new_vars = 105 let new_vars =
82 (0..solution.num_vars).map(|_| self.ctx.new_type_var()).collect::<Vec<_>>().into(); 106 (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into();
83 for (i, ty) in solution.value.into_iter().enumerate() { 107 for (i, ty) in solution.value.into_iter().enumerate() {
84 let var = self.free_vars[i].clone(); 108 let var = self.free_vars[i].clone();
85 self.ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 109 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
86 } 110 }
87 } 111 }
88} 112}