From 8d3469682681d5b206d5ae31fc63fb97d9cedb3a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 27 Nov 2019 22:12:09 +0300 Subject: Memoize impl resolutions --- crates/ra_hir_ty/src/db.rs | 5 ++++- crates/ra_hir_ty/src/infer/coerce.rs | 22 ++++++------------- crates/ra_hir_ty/src/infer/path.rs | 10 ++++----- crates/ra_hir_ty/src/lib.rs | 15 +++++++++++++ crates/ra_hir_ty/src/lower.rs | 35 ++++++++++++++++++++----------- crates/ra_hir_ty/src/method_resolution.rs | 30 +++++++++----------------- crates/ra_hir_ty/src/traits/chalk.rs | 34 +++++++++++++----------------- 7 files changed, 76 insertions(+), 75 deletions(-) diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index aa2659c4b..9ce154593 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId}; use crate::{ method_resolution::CrateImplBlocks, traits::{AssocTyValue, Impl}, - CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor, + CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor, ValueTyDefId, }; @@ -27,6 +27,9 @@ pub trait HirDatabase: DefDatabase { #[salsa::invoke(crate::lower::value_ty_query)] fn value_ty(&self, def: ValueTyDefId) -> Ty; + #[salsa::invoke(crate::lower::impl_ty_query)] + fn impl_ty(&self, def: ImplId) -> ImplTy; + #[salsa::invoke(crate::lower::field_types_query)] fn field_types(&self, var: VariantId) -> Arc>; diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index d66a21932..719a0f395 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -4,16 +4,11 @@ //! //! See: https://doc.rust-lang.org/nomicon/coercions.html -use hir_def::{ - lang_item::LangItemTarget, - resolver::{HasResolver, Resolver}, - type_ref::Mutability, - AdtId, -}; +use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AdtId}; use rustc_hash::FxHashMap; use test_utils::tested_by; -use crate::{autoderef, db::HirDatabase, Substs, TraitRef, Ty, TypeCtor, TypeWalk}; +use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; @@ -59,17 +54,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { impls .iter() .filter_map(|&impl_id| { - let impl_data = db.impl_data(impl_id); - let resolver = impl_id.resolver(db); - let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); + let trait_ref = match db.impl_ty(impl_id) { + ImplTy::TraitRef(it) => it, + ImplTy::Inherent(_) => return None, + }; // `CoerseUnsized` has one generic parameter for the target type. - let trait_ref = TraitRef::from_hir( - db, - &resolver, - impl_data.target_trait.as_ref()?, - Some(target_ty), - )?; let cur_from_ty = trait_ref.substs.0.get(0)?; let cur_to_ty = trait_ref.substs.0.get(1)?; diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index e6676e1aa..14be66836 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -2,7 +2,7 @@ use hir_def::{ path::{Path, PathKind, PathSegment}, - resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, + resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, AssocItemId, ContainerId, Lookup, }; use hir_expand::name::Name; @@ -244,17 +244,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ContainerId::ImplId(it) => it, _ => return None, }; - let resolver = impl_id.resolver(self.db); - let impl_data = self.db.impl_data(impl_id); - let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type); - let impl_block_substs = impl_block.substs()?; + let self_ty = self.db.impl_ty(impl_id).self_type().clone(); + let self_ty_substs = self_ty.substs()?; let actual_substs = actual_def_ty.substs()?; let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; // The following code *link up* the function actual parma type // and impl_block type param index - impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| { + self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| { if let Ty::Param { idx, .. } = param { if let Some(s) = new_substs.get_mut(*idx as usize) { *s = pty.clone(); diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index f25846326..c9ee34008 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -486,6 +486,21 @@ impl TypeWalk for TraitRef { } } +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ImplTy { + Inherent(Ty), + TraitRef(TraitRef), +} + +impl ImplTy { + pub(crate) fn self_type(&self) -> &Ty { + match self { + ImplTy::Inherent(it) => it, + ImplTy::TraitRef(tr) => &tr.substs[0], + } + } +} + /// Like `generics::WherePredicate`, but with resolved types: A condition on the /// parameters of a generic item. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 53d955a12..f8331d257 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -14,21 +14,21 @@ use hir_def::{ path::{GenericArg, Path, PathKind, PathSegment}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, + AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use ra_arena::map::ArenaMap; use ra_db::CrateId; -use super::{ - FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, - Ty, TypeCtor, TypeWalk, -}; use crate::{ db::HirDatabase, primitive::{FloatTy, IntTy}, - utils::make_mut_slice, - utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, + utils::{ + all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, + variant_data, + }, + FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, + TraitRef, Ty, TypeCtor, TypeWalk, }; impl Ty { @@ -179,11 +179,7 @@ impl Ty { let name = resolved_segment.name.clone(); Ty::Param { idx, name } } - TypeNs::SelfType(impl_id) => { - let impl_data = db.impl_data(impl_id); - let resolver = impl_id.resolver(db); - Ty::from_hir(db, &resolver, &impl_data.target_type) - } + TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(), TypeNs::AdtSelfType(adt) => db.ty(adt.into()), TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), @@ -751,3 +747,18 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { ValueTyDefId::StaticId(it) => type_for_static(db, it), } } + +pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy { + let impl_data = db.impl_data(impl_id); + let resolver = impl_id.resolver(db); + let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); + match impl_data.target_trait.as_ref() { + Some(trait_ref) => { + match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) { + Some(it) => ImplTy::TraitRef(it), + None => ImplTy::Inherent(self_ty), + } + } + None => ImplTy::Inherent(self_ty), + } +} diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 53c541eb8..ee1936b0e 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use arrayvec::ArrayVec; use hir_def::{ - lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability, - AssocItemId, AstItemDef, FunctionId, HasModule, ImplId, TraitId, + lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, + FunctionId, HasModule, ImplId, TraitId, }; use hir_expand::name::Name; use ra_db::CrateId; @@ -15,14 +15,13 @@ use ra_prof::profile; use rustc_hash::FxHashMap; use crate::{ + autoderef, db::HirDatabase, primitive::{FloatBitness, Uncertain}, utils::all_super_traits, - Ty, TypeCtor, + Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, }; -use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; - /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { @@ -59,22 +58,13 @@ impl CrateImplBlocks { let crate_def_map = db.crate_def_map(krate); for (_module_id, module_data) in crate_def_map.modules.iter() { for &impl_id in module_data.impls.iter() { - let impl_data = db.impl_data(impl_id); - let resolver = impl_id.resolver(db); - - let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); - - match &impl_data.target_trait { - Some(trait_ref) => { - if let Some(tr) = - TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)) - { - res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); - } + match db.impl_ty(impl_id) { + ImplTy::TraitRef(tr) => { + res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); } - None => { - if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { - res.impls.entry(target_ty_fp).or_default().push(impl_id); + ImplTy::Inherent(self_ty) => { + if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { + res.impls.entry(self_ty_fp).or_default().push(impl_id); } } } diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 810e8c21a..35de37e6b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -11,8 +11,8 @@ use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum use ra_db::CrateId; use hir_def::{ - expr::Expr, lang_item::LangItemTarget, resolver::HasResolver, AssocItemId, AstItemDef, - ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, + expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId, + ImplId, Lookup, TraitId, TypeAliasId, }; use hir_expand::name; @@ -20,9 +20,8 @@ use ra_db::salsa::{InternId, InternKey}; use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ - db::HirDatabase, - display::HirDisplay, - {ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, + db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy, + Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; /// This represents a trait whose name we could not resolve. @@ -631,13 +630,11 @@ fn impl_block_datum( chalk_id: chalk_ir::ImplId, impl_id: ImplId, ) -> Option>> { + let trait_ref = match db.impl_ty(impl_id) { + ImplTy::TraitRef(it) => it, + ImplTy::Inherent(_) => return None, + }; let impl_data = db.impl_data(impl_id); - let resolver = impl_id.resolver(db); - let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); - - // `CoerseUnsized` has one generic parameter for the target type. - let trait_ref = - TraitRef::from_hir(db, &resolver, impl_data.target_trait.as_ref()?, Some(target_ty))?; let generic_params = db.generic_params(impl_id.into()); let bound_vars = Substs::bound_vars(&generic_params); @@ -790,17 +787,14 @@ fn type_alias_associated_ty_value( _ => panic!("assoc ty value should be in impl"), }; - let impl_data = db.impl_data(impl_id); - let resolver = impl_id.resolver(db); - let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); - let target_trait = impl_data - .target_trait - .as_ref() - .and_then(|trait_ref| TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))) - .expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved + let trait_ref = match db.impl_ty(impl_id) { + ImplTy::TraitRef(it) => it, + // we don't return any assoc ty values if the impl'd trait can't be resolved + ImplTy::Inherent(_) => panic!("assoc ty value should not exist"), + }; let assoc_ty = db - .trait_data(target_trait.trait_) + .trait_data(trait_ref.trait_) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well let generic_params = db.generic_params(impl_id.into()); -- cgit v1.2.3