From d06904e90cdc1603ffcb714e70dab83905221f72 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 24 Nov 2019 23:48:39 +0300 Subject: Switch to variant-granularity field type inference --- crates/ra_hir/src/ty/infer/coerce.rs | 13 ++++++++----- crates/ra_hir/src/ty/infer/expr.rs | 11 ++++++++--- crates/ra_hir/src/ty/infer/pat.rs | 9 ++++++--- 3 files changed, 22 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir/src/ty/infer') diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 4ea038d99..54765da35 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs @@ -245,14 +245,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), ) if struct1 == struct2 => { - let fields = struct1.fields(self.db); - let (last_field, prev_fields) = fields.split_last()?; + let field_tys = self.db.field_types(struct1.id.into()); + let struct_data = self.db.struct_data(struct1.id.0); + + let mut fields = struct_data.variant_data.fields().iter(); + let (last_field_id, _data) = fields.next_back()?; // Get the generic parameter involved in the last field. let unsize_generic_index = { let mut index = None; let mut multiple_param = false; - last_field.ty(self.db).walk(&mut |ty| match ty { + field_tys[last_field_id].walk(&mut |ty| match ty { &Ty::Param { idx, .. } => { if index.is_none() { index = Some(idx); @@ -271,8 +274,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Check other fields do not involve it. let mut multiple_used = false; - prev_fields.iter().for_each(|field| { - field.ty(self.db).walk(&mut |ty| match ty { + fields.for_each(|(field_id, _data)| { + field_tys[field_id].walk(&mut |ty| match ty { &Ty::Param { idx, .. } if idx == unsize_generic_index => { multiple_used = true } diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index 2996920c6..663ff9435 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs @@ -214,6 +214,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.unify(&ty, &expected.ty); let substs = ty.substs().unwrap_or_else(Substs::empty); + let field_types = + def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); for (field_idx, field) in fields.iter().enumerate() { let field_def = def_id.and_then(|it| match it.field(self.db, &field.name) { Some(field) => Some(field), @@ -228,8 +230,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { if let Some(field_def) = field_def { self.result.record_field_resolutions.insert(field.expr, field_def); } - let field_ty = - field_def.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); + let field_ty = field_def + .map_or(Ty::Unknown, |it| field_types[it.id].clone()) + .subst(&substs); self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); } if let Some(expr) = spread { @@ -252,7 +255,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { self.write_field_resolution(tgt_expr, field); - field.ty(self.db).subst(&a_ty.parameters) + self.db.field_types(s.id.into())[field.id] + .clone() + .subst(&a_ty.parameters) }), _ => None, }, 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> { let substs = ty.substs().unwrap_or_else(Substs::empty); + let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); for (i, &subpat) in subpats.iter().enumerate() { let expected_ty = def .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) - .map_or(Ty::Unknown, |field| field.ty(self.db)) + .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) .subst(&substs); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat, &expected_ty, default_bm); @@ -56,10 +57,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let substs = ty.substs().unwrap_or_else(Substs::empty); + let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); for subpat in subpats { let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); - let expected_ty = - matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); + let expected_ty = matching_field + .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) + .subst(&substs); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat.pat, &expected_ty, default_bm); } -- cgit v1.2.3