diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer/expr.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 81 |
1 files changed, 51 insertions, 30 deletions
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 | } |