diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer')
-rw-r--r-- | crates/ra_hir/src/ty/infer/coerce.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 81 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/pat.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 5 |
4 files changed, 80 insertions, 48 deletions
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 0772b9df5..4b53bba73 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs | |||
@@ -4,18 +4,17 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::resolver::Resolver; | 7 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, | 12 | db::HirDatabase, |
13 | lang_item::LangItemTarget, | ||
14 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, | 13 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, |
15 | Adt, Mutability, | 14 | Adt, Mutability, |
16 | }; | 15 | }; |
17 | 16 | ||
18 | use super::{InferTy, InferenceContext, TypeVarValue}; | 17 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; |
19 | 18 | ||
20 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
21 | /// 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 |
@@ -50,7 +49,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
50 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { | 49 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { |
51 | let krate = resolver.krate().unwrap(); | 50 | let krate = resolver.krate().unwrap(); |
52 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { | 51 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { |
53 | Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), | 52 | Some(LangItemTarget::TraitId(trait_)) => { |
53 | db.impls_for_trait(krate.into(), trait_.into()) | ||
54 | } | ||
54 | _ => return FxHashMap::default(), | 55 | _ => return FxHashMap::default(), |
55 | }; | 56 | }; |
56 | 57 | ||
@@ -244,14 +245,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
244 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), | 245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), |
245 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), | 246 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), |
246 | ) if struct1 == struct2 => { | 247 | ) if struct1 == struct2 => { |
247 | let fields = struct1.fields(self.db); | 248 | let field_tys = self.db.field_types(struct1.id.into()); |
248 | 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()?; | ||
249 | 253 | ||
250 | // Get the generic parameter involved in the last field. | 254 | // Get the generic parameter involved in the last field. |
251 | let unsize_generic_index = { | 255 | let unsize_generic_index = { |
252 | let mut index = None; | 256 | let mut index = None; |
253 | let mut multiple_param = false; | 257 | let mut multiple_param = false; |
254 | last_field.ty(self.db).walk(&mut |ty| match ty { | 258 | field_tys[last_field_id].walk(&mut |ty| match ty { |
255 | &Ty::Param { idx, .. } => { | 259 | &Ty::Param { idx, .. } => { |
256 | if index.is_none() { | 260 | if index.is_none() { |
257 | index = Some(idx); | 261 | index = Some(idx); |
@@ -270,8 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
270 | 274 | ||
271 | // Check other fields do not involve it. | 275 | // Check other fields do not involve it. |
272 | let mut multiple_used = false; | 276 | let mut multiple_used = false; |
273 | prev_fields.iter().for_each(|field| { | 277 | fields.for_each(|(field_id, _data)| { |
274 | field.ty(self.db).walk(&mut |ty| match ty { | 278 | field_tys[field_id].walk(&mut |ty| match ty { |
275 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | 279 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { |
276 | multiple_used = true | 280 | multiple_used = true |
277 | } | 281 | } |
@@ -316,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
316 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | 320 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); |
317 | let to_ty = self.resolve_ty_shallow(&to_ty); | 321 | let to_ty = self.resolve_ty_shallow(&to_ty); |
318 | // FIXME: Auto DerefMut | 322 | // FIXME: Auto DerefMut |
319 | for derefed_ty in | 323 | for derefed_ty in autoderef::autoderef( |
320 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | 324 | self.db, |
321 | { | 325 | self.resolver.krate(), |
326 | InEnvironment { | ||
327 | value: canonicalized.value.clone(), | ||
328 | environment: self.trait_env.clone(), | ||
329 | }, | ||
330 | ) { | ||
322 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 331 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
323 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 332 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { |
324 | // 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 ac570075f..194e55819 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -5,6 +5,7 @@ use std::sync::Arc; | |||
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | builtin_type::Signedness, | 7 | builtin_type::Signedness, |
8 | generics::GenericParams, | ||
8 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
9 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
10 | }; | 11 | }; |
@@ -13,11 +14,10 @@ use hir_expand::name; | |||
13 | use crate::{ | 14 | use crate::{ |
14 | db::HirDatabase, | 15 | db::HirDatabase, |
15 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 16 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
16 | generics::{GenericParams, HasGenericParams}, | ||
17 | ty::{ | 17 | ty::{ |
18 | autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, | 18 | autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, |
19 | Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 19 | Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
20 | Uncertain, | 20 | TypeCtor, TypeWalk, Uncertain, |
21 | }, | 21 | }, |
22 | Adt, Name, | 22 | Adt, Name, |
23 | }; | 23 | }; |
@@ -214,19 +214,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
214 | self.unify(&ty, &expected.ty); | 214 | self.unify(&ty, &expected.ty); |
215 | 215 | ||
216 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 216 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
217 | let field_types = | ||
218 | def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | ||
217 | for (field_idx, field) in fields.iter().enumerate() { | 219 | for (field_idx, field) in fields.iter().enumerate() { |
218 | let field_ty = def_id | 220 | 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) { | 221 | Some(field) => Some(field), |
220 | Some(field) => Some(field), | 222 | None => { |
221 | None => { | 223 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { |
222 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { | 224 | expr: tgt_expr, |
223 | expr: tgt_expr, | 225 | field: field_idx, |
224 | field: field_idx, | 226 | }); |
225 | }); | 227 | None |
226 | None | 228 | } |
227 | } | 229 | }); |
228 | }) | 230 | if let Some(field_def) = field_def { |
229 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 231 | self.result.record_field_resolutions.insert(field.expr, field_def); |
232 | } | ||
233 | let field_ty = field_def | ||
234 | .map_or(Ty::Unknown, |it| field_types[it.id].clone()) | ||
230 | .subst(&substs); | 235 | .subst(&substs); |
231 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 236 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
232 | } | 237 | } |
@@ -240,8 +245,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
240 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); | 245 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
241 | let ty = autoderef::autoderef( | 246 | let ty = autoderef::autoderef( |
242 | self.db, | 247 | self.db, |
243 | &self.resolver.clone(), | 248 | self.resolver.krate(), |
244 | canonicalized.value.clone(), | 249 | InEnvironment { |
250 | value: canonicalized.value.clone(), | ||
251 | environment: self.trait_env.clone(), | ||
252 | }, | ||
245 | ) | 253 | ) |
246 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 254 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
247 | Ty::Apply(a_ty) => match a_ty.ctor { | 255 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -250,7 +258,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
250 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), | 258 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), |
251 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { | 259 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { |
252 | self.write_field_resolution(tgt_expr, field); | 260 | self.write_field_resolution(tgt_expr, field); |
253 | field.ty(self.db).subst(&a_ty.parameters) | 261 | self.db.field_types(s.id.into())[field.id] |
262 | .clone() | ||
263 | .subst(&a_ty.parameters) | ||
254 | }), | 264 | }), |
255 | _ => None, | 265 | _ => None, |
256 | }, | 266 | }, |
@@ -330,16 +340,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
330 | Expr::UnaryOp { expr, op } => { | 340 | Expr::UnaryOp { expr, op } => { |
331 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 341 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
332 | match op { | 342 | match op { |
333 | UnaryOp::Deref => { | 343 | UnaryOp::Deref => match self.resolver.krate() { |
334 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); | 344 | Some(krate) => { |
335 | if let Some(derefed_ty) = | 345 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); |
336 | autoderef::deref(self.db, &self.resolver, &canonicalized.value) | 346 | match autoderef::deref( |
337 | { | 347 | self.db, |
338 | canonicalized.decanonicalize_ty(derefed_ty.value) | 348 | krate, |
339 | } else { | 349 | InEnvironment { |
340 | Ty::Unknown | 350 | value: &canonicalized.value, |
351 | environment: self.trait_env.clone(), | ||
352 | }, | ||
353 | ) { | ||
354 | Some(derefed_ty) => { | ||
355 | canonicalized.decanonicalize_ty(derefed_ty.value) | ||
356 | } | ||
357 | None => Ty::Unknown, | ||
358 | } | ||
341 | } | 359 | } |
342 | } | 360 | None => Ty::Unknown, |
361 | }, | ||
343 | UnaryOp::Neg => { | 362 | UnaryOp::Neg => { |
344 | match &inner_ty { | 363 | match &inner_ty { |
345 | Ty::Apply(a_ty) => match a_ty.ctor { | 364 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -534,7 +553,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
534 | ( | 553 | ( |
535 | ty, | 554 | ty, |
536 | self.db.type_for_def(func.into(), Namespace::Values), | 555 | self.db.type_for_def(func.into(), Namespace::Values), |
537 | Some(func.generic_params(self.db)), | 556 | Some(self.db.generic_params(func.id.into())), |
538 | ) | 557 | ) |
539 | } | 558 | } |
540 | None => (receiver_ty, Ty::Unknown, None), | 559 | None => (receiver_ty, Ty::Unknown, None), |
@@ -645,7 +664,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
645 | if let Some(trait_) = f.parent_trait(self.db) { | 664 | if let Some(trait_) = f.parent_trait(self.db) { |
646 | // construct a TraitDef | 665 | // construct a TraitDef |
647 | let substs = a_ty.parameters.prefix( | 666 | let substs = a_ty.parameters.prefix( |
648 | trait_.generic_params(self.db).count_params_including_parent(), | 667 | self.db |
668 | .generic_params(trait_.id.into()) | ||
669 | .count_params_including_parent(), | ||
649 | ); | 670 | ); |
650 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | 671 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); |
651 | } | 672 | } |
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 70136e514..6165eba4f 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -7,7 +7,6 @@ use hir_def::{ | |||
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | db::HirDatabase, | 9 | db::HirDatabase, |
10 | generics::HasGenericParams, | ||
11 | ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, | 10 | ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, |
12 | AssocItem, Container, Function, Name, Path, | 11 | AssocItem, Container, Function, Name, Path, |
13 | }; | 12 | }; |
@@ -204,7 +203,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
204 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), | 203 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), |
205 | Container::Trait(t) => { | 204 | Container::Trait(t) => { |
206 | // we're picking this method | 205 | // we're picking this method |
207 | let trait_substs = Substs::build_for_def(self.db, t) | 206 | let trait_substs = Substs::build_for_def(self.db, t.id) |
208 | .push(ty.clone()) | 207 | .push(ty.clone()) |
209 | .fill(std::iter::repeat_with(|| self.new_type_var())) | 208 | .fill(std::iter::repeat_with(|| self.new_type_var())) |
210 | .build(); | 209 | .build(); |
@@ -230,7 +229,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
230 | if let ValueNs::FunctionId(func) = def { | 229 | if let ValueNs::FunctionId(func) = def { |
231 | let func = Function::from(*func); | 230 | let func = Function::from(*func); |
232 | // We only do the infer if parent has generic params | 231 | // We only do the infer if parent has generic params |
233 | let gen = func.generic_params(self.db); | 232 | let gen = self.db.generic_params(func.id.into()); |
234 | if gen.count_parent_params() == 0 { | 233 | if gen.count_parent_params() == 0 { |
235 | return None; | 234 | return None; |
236 | } | 235 | } |