aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer')
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs26
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs87
-rw-r--r--crates/ra_hir/src/ty/infer/pat.rs9
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs2
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
17use super::{InferTy, InferenceContext, TypeVarValue}; 17use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
18 18
19impl<'a, D: HirDatabase> InferenceContext<'a, D> { 19impl<'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};
12use hir_expand::name; 13use 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();