diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer')
-rw-r--r-- | crates/ra_hir/src/ty/infer/coerce.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 87 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/pat.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 2 |
4 files changed, 79 insertions, 45 deletions
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 4ea038d99..4b53bba73 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs | |||
@@ -14,7 +14,7 @@ use crate::{ | |||
14 | Adt, Mutability, | 14 | Adt, Mutability, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::{InferTy, InferenceContext, TypeVarValue}; | 17 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; |
18 | 18 | ||
19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
20 | /// Unify two types, but may coerce the first one to the second one | 20 | /// Unify two types, but may coerce the first one to the second one |
@@ -245,14 +245,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), | 245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), |
246 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), | 246 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), |
247 | ) if struct1 == struct2 => { | 247 | ) if struct1 == struct2 => { |
248 | let fields = struct1.fields(self.db); | 248 | let field_tys = self.db.field_types(struct1.id.into()); |
249 | let (last_field, prev_fields) = fields.split_last()?; | 249 | let struct_data = self.db.struct_data(struct1.id.0); |
250 | |||
251 | let mut fields = struct_data.variant_data.fields().iter(); | ||
252 | let (last_field_id, _data) = fields.next_back()?; | ||
250 | 253 | ||
251 | // Get the generic parameter involved in the last field. | 254 | // Get the generic parameter involved in the last field. |
252 | let unsize_generic_index = { | 255 | let unsize_generic_index = { |
253 | let mut index = None; | 256 | let mut index = None; |
254 | let mut multiple_param = false; | 257 | let mut multiple_param = false; |
255 | last_field.ty(self.db).walk(&mut |ty| match ty { | 258 | field_tys[last_field_id].walk(&mut |ty| match ty { |
256 | &Ty::Param { idx, .. } => { | 259 | &Ty::Param { idx, .. } => { |
257 | if index.is_none() { | 260 | if index.is_none() { |
258 | index = Some(idx); | 261 | index = Some(idx); |
@@ -271,8 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
271 | 274 | ||
272 | // Check other fields do not involve it. | 275 | // Check other fields do not involve it. |
273 | let mut multiple_used = false; | 276 | let mut multiple_used = false; |
274 | prev_fields.iter().for_each(|field| { | 277 | fields.for_each(|(field_id, _data)| { |
275 | field.ty(self.db).walk(&mut |ty| match ty { | 278 | field_tys[field_id].walk(&mut |ty| match ty { |
276 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | 279 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { |
277 | multiple_used = true | 280 | multiple_used = true |
278 | } | 281 | } |
@@ -317,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
317 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | 320 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); |
318 | let to_ty = self.resolve_ty_shallow(&to_ty); | 321 | let to_ty = self.resolve_ty_shallow(&to_ty); |
319 | // FIXME: Auto DerefMut | 322 | // FIXME: Auto DerefMut |
320 | for derefed_ty in | 323 | for derefed_ty in autoderef::autoderef( |
321 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | 324 | self.db, |
322 | { | 325 | self.resolver.krate(), |
326 | InEnvironment { | ||
327 | value: canonicalized.value.clone(), | ||
328 | environment: self.trait_env.clone(), | ||
329 | }, | ||
330 | ) { | ||
323 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 331 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
324 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 332 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { |
325 | // Stop when constructor matches. | 333 | // Stop when constructor matches. |
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index 20a7e9352..1d6df2b7a 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -8,6 +8,7 @@ use hir_def::{ | |||
8 | generics::GenericParams, | 8 | generics::GenericParams, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | ContainerId, Lookup, | ||
11 | }; | 12 | }; |
12 | use hir_expand::name; | 13 | use hir_expand::name; |
13 | 14 | ||
@@ -15,9 +16,9 @@ use crate::{ | |||
15 | db::HirDatabase, | 16 | db::HirDatabase, |
16 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 17 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
17 | ty::{ | 18 | ty::{ |
18 | autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, | 19 | autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, |
19 | Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 20 | Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
20 | Uncertain, | 21 | TypeCtor, TypeWalk, Uncertain, |
21 | }, | 22 | }, |
22 | Adt, Name, | 23 | Adt, Name, |
23 | }; | 24 | }; |
@@ -214,19 +215,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
214 | self.unify(&ty, &expected.ty); | 215 | self.unify(&ty, &expected.ty); |
215 | 216 | ||
216 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 217 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
218 | let field_types = | ||
219 | def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
217 | for (field_idx, field) in fields.iter().enumerate() { | 220 | for (field_idx, field) in fields.iter().enumerate() { |
218 | let field_ty = def_id | 221 | let field_def = def_id.and_then(|it| match it.field(self.db, &field.name) { |
219 | .and_then(|it| match it.field(self.db, &field.name) { | 222 | Some(field) => Some(field), |
220 | Some(field) => Some(field), | 223 | None => { |
221 | None => { | 224 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { |
222 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { | 225 | expr: tgt_expr, |
223 | expr: tgt_expr, | 226 | field: field_idx, |
224 | field: field_idx, | 227 | }); |
225 | }); | 228 | None |
226 | None | 229 | } |
227 | } | 230 | }); |
228 | }) | 231 | if let Some(field_def) = field_def { |
229 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 232 | self.result.record_field_resolutions.insert(field.expr, field_def); |
233 | } | ||
234 | let field_ty = field_def | ||
235 | .map_or(Ty::Unknown, |it| field_types[it.id].clone()) | ||
230 | .subst(&substs); | 236 | .subst(&substs); |
231 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 237 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
232 | } | 238 | } |
@@ -240,8 +246,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
240 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); | 246 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
241 | let ty = autoderef::autoderef( | 247 | let ty = autoderef::autoderef( |
242 | self.db, | 248 | self.db, |
243 | &self.resolver.clone(), | 249 | self.resolver.krate(), |
244 | canonicalized.value.clone(), | 250 | InEnvironment { |
251 | value: canonicalized.value.clone(), | ||
252 | environment: self.trait_env.clone(), | ||
253 | }, | ||
245 | ) | 254 | ) |
246 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 255 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
247 | Ty::Apply(a_ty) => match a_ty.ctor { | 256 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -250,7 +259,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
250 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), | 259 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), |
251 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { | 260 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { |
252 | self.write_field_resolution(tgt_expr, field); | 261 | self.write_field_resolution(tgt_expr, field); |
253 | field.ty(self.db).subst(&a_ty.parameters) | 262 | self.db.field_types(s.id.into())[field.id] |
263 | .clone() | ||
264 | .subst(&a_ty.parameters) | ||
254 | }), | 265 | }), |
255 | _ => None, | 266 | _ => None, |
256 | }, | 267 | }, |
@@ -330,16 +341,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
330 | Expr::UnaryOp { expr, op } => { | 341 | Expr::UnaryOp { expr, op } => { |
331 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 342 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
332 | match op { | 343 | match op { |
333 | UnaryOp::Deref => { | 344 | UnaryOp::Deref => match self.resolver.krate() { |
334 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); | 345 | Some(krate) => { |
335 | if let Some(derefed_ty) = | 346 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); |
336 | autoderef::deref(self.db, &self.resolver, &canonicalized.value) | 347 | match autoderef::deref( |
337 | { | 348 | self.db, |
338 | canonicalized.decanonicalize_ty(derefed_ty.value) | 349 | krate, |
339 | } else { | 350 | InEnvironment { |
340 | Ty::Unknown | 351 | value: &canonicalized.value, |
352 | environment: self.trait_env.clone(), | ||
353 | }, | ||
354 | ) { | ||
355 | Some(derefed_ty) => { | ||
356 | canonicalized.decanonicalize_ty(derefed_ty.value) | ||
357 | } | ||
358 | None => Ty::Unknown, | ||
359 | } | ||
341 | } | 360 | } |
342 | } | 361 | None => Ty::Unknown, |
362 | }, | ||
343 | UnaryOp::Neg => { | 363 | UnaryOp::Neg => { |
344 | match &inner_ty { | 364 | match &inner_ty { |
345 | Ty::Apply(a_ty) => match a_ty.ctor { | 365 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -641,18 +661,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
641 | } | 661 | } |
642 | // add obligation for trait implementation, if this is a trait method | 662 | // add obligation for trait implementation, if this is a trait method |
643 | match def { | 663 | match def { |
644 | CallableDef::Function(f) => { | 664 | CallableDef::FunctionId(f) => { |
645 | if let Some(trait_) = f.parent_trait(self.db) { | 665 | if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { |
646 | // construct a TraitDef | 666 | // construct a TraitDef |
647 | let substs = a_ty.parameters.prefix( | 667 | let substs = a_ty.parameters.prefix( |
648 | self.db | 668 | self.db |
649 | .generic_params(trait_.id.into()) | 669 | .generic_params(trait_.into()) |
650 | .count_params_including_parent(), | 670 | .count_params_including_parent(), |
651 | ); | 671 | ); |
652 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | 672 | self.obligations.push(Obligation::Trait(TraitRef { |
673 | trait_: trait_.into(), | ||
674 | substs, | ||
675 | })); | ||
653 | } | 676 | } |
654 | } | 677 | } |
655 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {} | 678 | CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {} |
656 | } | 679 | } |
657 | } | 680 | } |
658 | } | 681 | } |
diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir/src/ty/infer/pat.rs index c125ddfbc..641d61e87 100644 --- a/crates/ra_hir/src/ty/infer/pat.rs +++ b/crates/ra_hir/src/ty/infer/pat.rs | |||
@@ -27,10 +27,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
27 | 27 | ||
28 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 28 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
29 | 29 | ||
30 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
30 | for (i, &subpat) in subpats.iter().enumerate() { | 31 | for (i, &subpat) in subpats.iter().enumerate() { |
31 | let expected_ty = def | 32 | let expected_ty = def |
32 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) | 33 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) |
33 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 34 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) |
34 | .subst(&substs); | 35 | .subst(&substs); |
35 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 36 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
36 | self.infer_pat(subpat, &expected_ty, default_bm); | 37 | self.infer_pat(subpat, &expected_ty, default_bm); |
@@ -56,10 +57,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
56 | 57 | ||
57 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 58 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
58 | 59 | ||
60 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
59 | for subpat in subpats { | 61 | for subpat in subpats { |
60 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); | 62 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); |
61 | let expected_ty = | 63 | let expected_ty = matching_field |
62 | matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); | 64 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) |
65 | .subst(&substs); | ||
63 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 66 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
64 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 67 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
65 | } | 68 | } |
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index ee54d8217..6165eba4f 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -203,7 +203,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
203 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), | 203 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), |
204 | Container::Trait(t) => { | 204 | Container::Trait(t) => { |
205 | // we're picking this method | 205 | // we're picking this method |
206 | let trait_substs = Substs::build_for_def(self.db, t) | 206 | let trait_substs = Substs::build_for_def(self.db, t.id) |
207 | .push(ty.clone()) | 207 | .push(ty.clone()) |
208 | .fill(std::iter::repeat_with(|| self.new_type_var())) | 208 | .fill(std::iter::repeat_with(|| self.new_type_var())) |
209 | .build(); | 209 | .build(); |