From bb6e1bf811bce09fdab115a4257e47cc0d5ddc82 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 24 Mar 2021 17:00:29 +0100 Subject: Lower traits to TraitRef instead of TypeRef --- crates/hir/src/lib.rs | 3 ++- crates/hir_def/src/data.rs | 4 ++-- crates/hir_def/src/item_tree.rs | 41 +++++++++++++++++++++++++++++++++-- crates/hir_def/src/item_tree/lower.rs | 10 +++++++-- crates/hir_def/src/type_ref.rs | 19 ++++++++++++++++ crates/hir_ty/src/lower.rs | 13 +++++------ 6 files changed, 76 insertions(+), 14 deletions(-) (limited to 'crates') diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4ee08ef21..99d858eb3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -44,6 +44,7 @@ use hir_def::{ per_ns::PerNs, resolver::{HasResolver, Resolver}, src::HasSource as _, + type_ref::TraitRef, AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, @@ -1613,7 +1614,7 @@ impl Impl { // FIXME: the return type is wrong. This should be a hir version of // `TraitRef` (ie, resolved `TypeRef`). - pub fn target_trait(self, db: &dyn HirDatabase) -> Option { + pub fn target_trait(self, db: &dyn HirDatabase) -> Option { db.impl_data(self.id).target_trait.clone() } diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 0be868ba2..7d35d7083 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -10,7 +10,7 @@ use crate::{ body::Expander, db::DefDatabase, item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, - type_ref::{TypeBound, TypeRef}, + type_ref::{TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, @@ -156,7 +156,7 @@ impl TraitData { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ImplData { - pub target_trait: Option, + pub target_trait: Option, pub target_type: TypeRef, pub items: Vec, pub is_negative: bool, diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ca0048b16..db94bb1ef 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -31,7 +31,7 @@ use crate::{ db::DefDatabase, generics::GenericParams, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, - type_ref::{Mutability, TypeBound, TypeRef}, + type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, }; @@ -147,6 +147,7 @@ impl ItemTree { vis, generics, type_refs, + trait_refs, inner_items, } = &mut **data; @@ -173,6 +174,7 @@ impl ItemTree { generics.arena.shrink_to_fit(); type_refs.arena.shrink_to_fit(); type_refs.map.shrink_to_fit(); + trait_refs.map.shrink_to_fit(); inner_items.shrink_to_fit(); } @@ -295,6 +297,32 @@ impl TypeRefStorage { } } +/// `TraitRef` interner. +#[derive(Default, Debug, Eq, PartialEq)] +struct TraitRefStorage { + arena: Arena>, + map: FxHashMap, Idx>>, +} + +impl TraitRefStorage { + // Note: We lie about the `Idx` to hide the interner details. + + fn intern(&mut self, ty: TraitRef) -> Idx { + if let Some(id) = self.map.get(&ty) { + return Idx::from_raw(id.into_raw()); + } + + let ty = Arc::new(ty); + let idx = self.arena.alloc(ty.clone()); + self.map.insert(ty, idx); + Idx::from_raw(idx.into_raw()) + } + + fn lookup(&self, id: Idx) -> &TraitRef { + &self.arena[Idx::from_raw(id.into_raw())] + } +} + #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { imports: Arena, @@ -319,6 +347,7 @@ struct ItemTreeData { vis: ItemVisibilities, generics: GenericParamsStorage, type_refs: TypeRefStorage, + trait_refs: TraitRefStorage, inner_items: FxHashMap, SmallVec<[ModItem; 1]>>, } @@ -556,6 +585,14 @@ impl Index> for ItemTree { } } +impl Index> for ItemTree { + type Output = TraitRef; + + fn index(&self, id: Idx) -> &Self::Output { + self.data().trait_refs.lookup(id) + } +} + impl Index> for ItemTree { type Output = N; fn index(&self, id: FileItemTreeId) -> &N { @@ -692,7 +729,7 @@ pub struct Trait { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { pub generic_params: GenericParamsId, - pub target_trait: Option>, + pub target_trait: Option>, pub target_type: Idx, pub is_negative: bool, pub items: Box<[AssocItem]>, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 3f558edd8..34af5c8d4 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -11,7 +11,7 @@ use syntax::{ use crate::{ generics::{GenericParams, TypeParamData, TypeParamProvenance}, - type_ref::LifetimeRef, + type_ref::{LifetimeRef, TraitRef}, }; use super::*; @@ -536,7 +536,7 @@ impl Ctx { fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option> { let generic_params = self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); - let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr)); + let target_trait = impl_def.trait_().map(|tr| self.lower_trait_ref(&tr)); let target_type = self.lower_type_ref(&impl_def.self_ty()?); let is_negative = impl_def.excl_token().is_some(); @@ -740,10 +740,16 @@ impl Ctx { self.data().vis.alloc(vis) } + fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Idx { + let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone()); + self.data().trait_refs.intern(trait_ref) + } + fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx { let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); self.data().type_refs.intern(tyref) } + fn lower_type_ref_opt(&mut self, type_ref: Option) -> Idx { match type_ref.map(|ty| self.lower_type_ref(&ty)) { Some(it) => it, diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 049b2e462..b7484ed0d 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs @@ -51,6 +51,25 @@ impl Rawness { } } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum TraitRef { + Path(Path), + Error, +} + +impl TraitRef { + /// Converts an `ast::PathType` to a `hir::TraitRef`. + pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self { + // FIXME: Use `Path::from_src` + match node { + ast::Type::PathType(path) => path + .path() + .and_then(|it| ctx.lower_path(it)) + .map_or(TraitRef::Error, TraitRef::Path), + _ => TraitRef::Error, + } + } +} /// Compare ty::Ty #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum TypeRef { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index c87789d45..9b99268e2 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -15,7 +15,7 @@ use hir_def::{ generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, - type_ref::{TypeBound, TypeRef}, + type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef}, AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, @@ -667,14 +667,13 @@ impl<'a> TyLoweringContext<'a> { fn lower_trait_ref( &self, - type_ref: &TypeRef, + trait_ref: &HirTraitRef, explicit_self_ty: Option, ) -> Option { - let path = match type_ref { - TypeRef::Path(path) => path, - _ => return None, - }; - self.lower_trait_ref_from_path(path, explicit_self_ty) + match trait_ref { + HirTraitRef::Path(path) => self.lower_trait_ref_from_path(path, explicit_self_ty), + HirTraitRef::Error => None, + } } fn trait_ref_substs_from_path( -- cgit v1.2.3