aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer/expr.rs')
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs81
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
6use hir_def::{ 6use 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;
13use crate::{ 14use 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 }