diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 55 |
2 files changed, 55 insertions, 25 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 22884522a..731b062c2 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | autoderef, method_resolution, op, | 17 | autoderef, method_resolution, op, |
18 | traits::{FnTrait, InEnvironment}, | 18 | traits::{FnTrait, InEnvironment}, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, | 20 | ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, |
21 | TraitRef, Ty, TypeCtor, | 21 | TraitRef, Ty, TypeCtor, |
22 | }; | 22 | }; |
23 | 23 | ||
@@ -85,10 +85,8 @@ impl<'a> InferenceContext<'a> { | |||
85 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, | 85 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, |
86 | parameters, | 86 | parameters, |
87 | }); | 87 | }); |
88 | let substs = Substs::build_for_generics(&generic_params) | 88 | let substs = |
89 | .push(ty.clone()) | 89 | Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
90 | .push(arg_ty.clone()) | ||
91 | .build(); | ||
92 | 90 | ||
93 | let trait_env = Arc::clone(&self.trait_env); | 91 | let trait_env = Arc::clone(&self.trait_env); |
94 | let implements_fn_trait = | 92 | let implements_fn_trait = |
@@ -222,7 +220,7 @@ impl<'a> InferenceContext<'a> { | |||
222 | }; | 220 | }; |
223 | sig_tys.push(ret_ty.clone()); | 221 | sig_tys.push(ret_ty.clone()); |
224 | let sig_ty = Ty::apply( | 222 | let sig_ty = Ty::apply( |
225 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | 223 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false }, |
226 | Substs(sig_tys.clone().into()), | 224 | Substs(sig_tys.clone().into()), |
227 | ); | 225 | ); |
228 | let closure_ty = | 226 | let closure_ty = |
@@ -407,8 +405,15 @@ impl<'a> InferenceContext<'a> { | |||
407 | .subst(&a_ty.parameters) | 405 | .subst(&a_ty.parameters) |
408 | }) | 406 | }) |
409 | } | 407 | } |
410 | // FIXME: | 408 | TypeCtor::Adt(AdtId::UnionId(u)) => { |
411 | TypeCtor::Adt(AdtId::UnionId(_)) => None, | 409 | self.db.union_data(u).variant_data.field(name).map(|local_id| { |
410 | let field = FieldId { parent: u.into(), local_id }; | ||
411 | self.write_field_resolution(tgt_expr, field); | ||
412 | self.db.field_types(u.into())[field.local_id] | ||
413 | .clone() | ||
414 | .subst(&a_ty.parameters) | ||
415 | }) | ||
416 | } | ||
412 | _ => None, | 417 | _ => None, |
413 | }, | 418 | }, |
414 | _ => None, | 419 | _ => None, |
@@ -849,7 +854,7 @@ impl<'a> InferenceContext<'a> { | |||
849 | } | 854 | } |
850 | // add obligation for trait implementation, if this is a trait method | 855 | // add obligation for trait implementation, if this is a trait method |
851 | match def { | 856 | match def { |
852 | CallableDef::FunctionId(f) => { | 857 | CallableDefId::FunctionId(f) => { |
853 | if let AssocContainerId::TraitId(trait_) = | 858 | if let AssocContainerId::TraitId(trait_) = |
854 | f.lookup(self.db.upcast()).container | 859 | f.lookup(self.db.upcast()).container |
855 | { | 860 | { |
@@ -860,7 +865,7 @@ impl<'a> InferenceContext<'a> { | |||
860 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | 865 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); |
861 | } | 866 | } |
862 | } | 867 | } |
863 | CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {} | 868 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} |
864 | } | 869 | } |
865 | } | 870 | } |
866 | } | 871 | } |
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index 269495ca0..2e895d911 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs | |||
@@ -9,7 +9,7 @@ use test_utils::mark; | |||
9 | use super::{InferenceContext, Obligation}; | 9 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 10 | use crate::{ |
11 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, | 11 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, |
12 | TypeCtor, TypeWalk, | 12 | TyKind, TypeCtor, TypeWalk, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | impl<'a> InferenceContext<'a> { | 15 | impl<'a> InferenceContext<'a> { |
@@ -86,10 +86,20 @@ where | |||
86 | } | 86 | } |
87 | 87 | ||
88 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 88 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
89 | Canonicalized { | 89 | let kinds = self |
90 | value: Canonical { value: result, num_vars: self.free_vars.len() }, | 90 | .free_vars |
91 | free_vars: self.free_vars, | 91 | .iter() |
92 | } | 92 | .map(|v| match v { |
93 | // mapping MaybeNeverTypeVar to the same kind as general ones | ||
94 | // should be fine, because as opposed to int or float type vars, | ||
95 | // they don't restrict what kind of type can go into them, they | ||
96 | // just affect fallback. | ||
97 | InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General, | ||
98 | InferTy::IntVar(_) => TyKind::Integer, | ||
99 | InferTy::FloatVar(_) => TyKind::Float, | ||
100 | }) | ||
101 | .collect(); | ||
102 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | ||
93 | } | 103 | } |
94 | 104 | ||
95 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 105 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -131,26 +141,41 @@ impl<T> Canonicalized<T> { | |||
131 | ty | 141 | ty |
132 | } | 142 | } |
133 | 143 | ||
134 | pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Vec<Ty>>) { | 144 | pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Substs>) { |
135 | // the solution may contain new variables, which we need to convert to new inference vars | 145 | // the solution may contain new variables, which we need to convert to new inference vars |
136 | let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect()); | 146 | let new_vars = Substs( |
147 | solution | ||
148 | .kinds | ||
149 | .iter() | ||
150 | .map(|k| match k { | ||
151 | TyKind::General => ctx.table.new_type_var(), | ||
152 | TyKind::Integer => ctx.table.new_integer_var(), | ||
153 | TyKind::Float => ctx.table.new_float_var(), | ||
154 | }) | ||
155 | .collect(), | ||
156 | ); | ||
137 | for (i, ty) in solution.value.into_iter().enumerate() { | 157 | for (i, ty) in solution.value.into_iter().enumerate() { |
138 | let var = self.free_vars[i]; | 158 | let var = self.free_vars[i]; |
139 | // eagerly replace projections in the type; we may be getting types | 159 | // eagerly replace projections in the type; we may be getting types |
140 | // e.g. from where clauses where this hasn't happened yet | 160 | // e.g. from where clauses where this hasn't happened yet |
141 | let ty = ctx.normalize_associated_types_in(ty.subst_bound_vars(&new_vars)); | 161 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); |
142 | ctx.table.unify(&Ty::Infer(var), &ty); | 162 | ctx.table.unify(&Ty::Infer(var), &ty); |
143 | } | 163 | } |
144 | } | 164 | } |
145 | } | 165 | } |
146 | 166 | ||
147 | pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { | 167 | pub fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { |
148 | let mut table = InferenceTable::new(); | 168 | let mut table = InferenceTable::new(); |
149 | let num_vars = ty1.num_vars.max(ty2.num_vars); | 169 | let vars = Substs( |
150 | let vars = | 170 | tys.kinds |
151 | Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); | 171 | .iter() |
152 | let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars); | 172 | // we always use type vars here because we want everything to |
153 | let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars); | 173 | // fallback to Unknown in the end (kind of hacky, as below) |
174 | .map(|_| table.new_type_var()) | ||
175 | .collect(), | ||
176 | ); | ||
177 | let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); | ||
178 | let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); | ||
154 | if !table.unify(&ty1_with_vars, &ty2_with_vars) { | 179 | if !table.unify(&ty1_with_vars, &ty2_with_vars) { |
155 | return None; | 180 | return None; |
156 | } | 181 | } |
@@ -162,7 +187,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { | |||
162 | } | 187 | } |
163 | } | 188 | } |
164 | Some( | 189 | Some( |
165 | Substs::builder(ty1.num_vars) | 190 | Substs::builder(tys.kinds.len()) |
166 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 191 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
167 | .build(), | 192 | .build(), |
168 | ) | 193 | ) |