From 9fa46ff5c67bd1809cc748f6fc0e93d7c9be3fdb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 27 Nov 2019 16:25:01 +0300 Subject: Use Id for variats --- crates/ra_hir/src/ty/infer.rs | 18 +++++++++--------- crates/ra_hir/src/ty/infer/expr.rs | 34 +++++++++++++++++++--------------- crates/ra_hir/src/ty/infer/pat.rs | 20 +++++++++++--------- crates/ra_hir/src/ty/lower.rs | 14 ++++++-------- crates/ra_hir/src/ty/utils.rs | 14 +++++++++++++- 5 files changed, 58 insertions(+), 42 deletions(-) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 1eca4883d..59e4e5f36 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -28,7 +28,7 @@ use hir_def::{ path::{known, Path}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{Mutability, TypeRef}, - AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, + AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, }; use hir_expand::{diagnostics::DiagnosticSink, name}; use ra_arena::map::ArenaMap; @@ -41,7 +41,7 @@ use super::{ ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, }; -use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic, VariantDef}; +use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic}; macro_rules! ty_app { ($ctor:pat, $param:pat) => { @@ -124,7 +124,7 @@ pub struct InferenceResult { /// For each field in record literal, records the field it resolves to. record_field_resolutions: FxHashMap, /// For each struct literal, records the variant it resolves to. - variant_resolutions: FxHashMap, + variant_resolutions: FxHashMap, /// For each associated item record what it resolves to assoc_resolutions: FxHashMap, diagnostics: Vec, @@ -143,10 +143,10 @@ impl InferenceResult { pub fn record_field_resolution(&self, expr: ExprId) -> Option { self.record_field_resolutions.get(&expr).copied() } - pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option { + pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option { self.variant_resolutions.get(&id.into()).copied() } - pub fn variant_resolution_for_pat(&self, id: PatId) -> Option { + pub fn variant_resolution_for_pat(&self, id: PatId) -> Option { self.variant_resolutions.get(&id.into()).copied() } pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option { @@ -248,7 +248,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.result.field_resolutions.insert(expr, field); } - fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantDef) { + fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) { self.result.variant_resolutions.insert(id, variant); } @@ -511,7 +511,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }) } - fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { + fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { let path = match path { Some(path) => path, None => return (Ty::Unknown, None), @@ -524,13 +524,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); let ty = self.db.ty(strukt.into()); let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(VariantDef::Struct(strukt.into()))) + (ty, Some(strukt.into())) } Some(TypeNs::EnumVariantId(var)) => { let substs = Ty::substs_from_path(self.db, resolver, path, var.into()); let ty = self.db.ty(var.parent.into()); let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(VariantDef::EnumVariant(var.into()))) + (ty, Some(var.into())) } Some(_) | None => (Ty::Unknown, None), } diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index d9ea6da42..f9ededa23 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs @@ -16,9 +16,9 @@ use hir_expand::name::{self, Name}; use crate::{ db::HirDatabase, ty::{ - autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, - Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, - TypeWalk, Uncertain, + autoderef, method_resolution, op, traits::InEnvironment, utils::variant_data, CallableDef, + InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, + TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, }, }; @@ -218,22 +218,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { 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(); + let variant_data = def_id.map(|it| variant_data(self.db, it)); 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), - None => { - self.push_diagnostic(InferenceDiagnostic::NoSuchField { - expr: tgt_expr, - field: field_idx, - }); - None - } - }); + let field_def = + variant_data.as_ref().and_then(|it| match it.field(&field.name) { + Some(local_id) => { + Some(StructFieldId { parent: def_id.unwrap(), local_id }) + } + None => { + self.push_diagnostic(InferenceDiagnostic::NoSuchField { + expr: tgt_expr, + field: field_idx, + }); + None + } + }); if let Some(field_def) = field_def { - self.result.record_field_resolutions.insert(field.expr, field_def.into()); + self.result.record_field_resolutions.insert(field.expr, field_def); } let field_ty = field_def - .map_or(Ty::Unknown, |it| field_types[it.id].clone()) + .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) .subst(&substs); self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); } diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir/src/ty/infer/pat.rs index 6dbf03eb2..a14774607 100644 --- a/crates/ra_hir/src/ty/infer/pat.rs +++ b/crates/ra_hir/src/ty/infer/pat.rs @@ -14,7 +14,7 @@ use test_utils::tested_by; use super::{BindingMode, InferenceContext}; use crate::{ db::HirDatabase, - ty::{Substs, Ty, TypeCtor, TypeWalk}, + ty::{utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}, }; impl<'a, D: HirDatabase> InferenceContext<'a, D> { @@ -26,16 +26,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { default_bm: BindingMode, ) -> Ty { let (ty, def) = self.resolve_variant(path); - + let var_data = def.map(|it| variant_data(self.db, it)); self.unify(&ty, expected); 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_tys[field.id].clone()) + let expected_ty = var_data + .as_ref() + .and_then(|d| d.field(&Name::new_tuple_field(i))) + .map_or(Ty::Unknown, |field| field_tys[field].clone()) .subst(&substs); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat, &expected_ty, default_bm); @@ -53,6 +55,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { id: PatId, ) -> Ty { let (ty, def) = self.resolve_variant(path); + let var_data = def.map(|it| variant_data(self.db, it)); if let Some(variant) = def { self.write_variant_resolution(id.into(), variant); } @@ -63,10 +66,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { 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_tys[field.id].clone()) - .subst(&substs); + let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); + let expected_ty = + matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs); let expected_ty = self.normalize_associated_types_in(expected_ty); self.infer_pat(subpat.pat, &expected_ty, default_bm); } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 1c0f71adc..d33b50794 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -28,7 +28,7 @@ use crate::{ db::HirDatabase, ty::{ primitive::{FloatTy, IntTy}, - utils::{all_super_traits, associated_type_by_name_including_super_traits}, + utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, }, util::make_mut_slice, Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, @@ -514,13 +514,11 @@ pub(crate) fn field_types_query( db: &impl HirDatabase, variant_id: VariantId, ) -> Arc> { - let (resolver, var_data) = match variant_id { - VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()), - VariantId::UnionId(it) => (it.resolver(db), db.union_data(it).variant_data.clone()), - VariantId::EnumVariantId(it) => ( - it.parent.resolver(db), - db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), - ), + let var_data = variant_data(db, variant_id); + let resolver = match variant_id { + VariantId::StructId(it) => it.resolver(db), + VariantId::UnionId(it) => it.resolver(db), + VariantId::EnumVariantId(it) => it.parent.resolver(db), }; let mut res = ArenaMap::default(); for (field_id, field_data) in var_data.fields().iter() { diff --git a/crates/ra_hir/src/ty/utils.rs b/crates/ra_hir/src/ty/utils.rs index 80ffceb4b..f82e6ac9b 100644 --- a/crates/ra_hir/src/ty/utils.rs +++ b/crates/ra_hir/src/ty/utils.rs @@ -1,11 +1,13 @@ //! Helper functions for working with def, which don't need to be a separate //! query, but can't be computed directly from `*Data` (ie, which need a `db`). +use std::sync::Arc; use hir_def::{ + adt::VariantData, db::DefDatabase, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, - TraitId, TypeAliasId, + TraitId, TypeAliasId, VariantId, }; use hir_expand::name::{self, Name}; @@ -61,3 +63,13 @@ pub(super) fn associated_type_by_name_including_super_traits( .into_iter() .find_map(|t| db.trait_data(t).associated_type_by_name(name)) } + +pub(super) fn variant_data(db: &impl DefDatabase, var: VariantId) -> Arc { + match var { + VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), + VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), + VariantId::EnumVariantId(it) => { + db.enum_data(it.parent).variants[it.local_id].variant_data.clone() + } + } +} -- cgit v1.2.3