From 8ebb8d29e18d7cb18bd2b57b004dcecd65a96232 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 24 May 2021 15:13:23 +0200 Subject: internal: intern `TypeBound`s Doesn't save much memory (~2 mb), but interning things is generally a good pattern to follow --- crates/hir/src/display.rs | 2 +- crates/hir_def/src/data.rs | 4 ++-- crates/hir_def/src/generics.rs | 20 +++++++++++++++----- crates/hir_def/src/intern.rs | 1 + crates/hir_def/src/item_tree.rs | 4 ++-- crates/hir_def/src/item_tree/lower.rs | 11 ++++++----- crates/hir_def/src/item_tree/pretty.rs | 4 ++-- crates/hir_def/src/path.rs | 2 +- crates/hir_def/src/path/lower.rs | 4 +++- crates/hir_def/src/type_ref.rs | 14 +++++++------- crates/hir_ty/src/display.rs | 7 +++++++ crates/hir_ty/src/lower.rs | 3 ++- 12 files changed, 49 insertions(+), 27 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 508ac37c2..c5cf803fd 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -92,7 +92,7 @@ impl HirDisplay for Function { &data.ret_type } else { match &*data.ret_type { - TypeRef::ImplTrait(bounds) => match &bounds[0] { + TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() { TypeBound::Path(path) => { path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings [0] diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 135a6698e..8bcac60ef 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -112,7 +112,7 @@ pub struct TypeAliasData { pub visibility: RawVisibility, pub is_extern: bool, /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). - pub bounds: Vec, + pub bounds: Vec>, } impl TypeAliasData { @@ -141,7 +141,7 @@ pub struct TraitData { pub is_auto: bool, pub is_unsafe: bool, pub visibility: RawVisibility, - pub bounds: Box<[TypeBound]>, + pub bounds: Box<[Interned]>, } impl TraitData { diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index de5acced8..44d22b918 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -68,9 +68,19 @@ pub struct GenericParams { /// associated type bindings like `Iterator`. #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum WherePredicate { - TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, - Lifetime { target: LifetimeRef, bound: LifetimeRef }, - ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, + TypeBound { + target: WherePredicateTypeTarget, + bound: Interned, + }, + Lifetime { + target: LifetimeRef, + bound: LifetimeRef, + }, + ForLifetime { + lifetimes: Box<[Name]>, + target: WherePredicateTypeTarget, + bound: Interned, + }, } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -339,11 +349,11 @@ impl GenericParams { Some(hrtb_lifetimes) => WherePredicate::ForLifetime { lifetimes: hrtb_lifetimes.clone(), target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), - bound, + bound: Interned::new(bound), }, None => WherePredicate::TypeBound { target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), - bound, + bound: Interned::new(bound), }, }, (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index 5cc7f2df6..8b3f799e2 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs @@ -216,6 +216,7 @@ pub use crate::_impl_internable as impl_internable; impl_internable!( crate::type_ref::TypeRef, crate::type_ref::TraitRef, + crate::type_ref::TypeBound, crate::path::ModPath, GenericParams, str, diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 4a5f44027..11767d100 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -644,7 +644,7 @@ pub struct Trait { pub generic_params: Interned, pub is_auto: bool, pub is_unsafe: bool, - pub bounds: Box<[TypeBound]>, + pub bounds: Box<[Interned]>, pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } @@ -664,7 +664,7 @@ pub struct TypeAlias { pub name: Name, pub visibility: RawVisibilityId, /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. - pub bounds: Box<[TypeBound]>, + pub bounds: Box<[Interned]>, pub generic_params: Interned, pub type_ref: Option>, pub is_extern: bool, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 91cf75371..1a0e54413 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -384,7 +384,7 @@ impl<'a> Ctx<'a> { let ret_type = if func.async_token().is_some() { let future_impl = desugar_future_path(ret_type); - let ty_bound = TypeBound::Path(future_impl); + let ty_bound = Interned::new(TypeBound::Path(future_impl)); TypeRef::ImplTrait(vec![ty_bound]) } else { ret_type @@ -738,11 +738,12 @@ impl<'a> Ctx<'a> { Interned::new(generics) } - fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec { + fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec> { match node.type_bound_list() { - Some(bound_list) => { - bound_list.bounds().map(|it| TypeBound::from_ast(&self.body_ctx, it)).collect() - } + Some(bound_list) => bound_list + .bounds() + .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it))) + .collect(), None => Vec::new(), } } diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index 4bc87a0e2..9394a5de6 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs @@ -513,13 +513,13 @@ impl<'a> Printer<'a> { } } - fn print_type_bounds(&mut self, bounds: &[TypeBound]) { + fn print_type_bounds(&mut self, bounds: &[Interned]) { for (i, bound) in bounds.iter().enumerate() { if i != 0 { w!(self, " + "); } - match bound { + match bound.as_ref() { TypeBound::Path(path) => self.print_path(path), TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), TypeBound::Error => w!(self, "{{unknown}}"), diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 9b8873fd2..7bd7d9d4f 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs @@ -165,7 +165,7 @@ pub struct AssociatedTypeBinding { /// Bounds for the associated type, like in `Iterator`. (This is the unstable `associated_type_bounds` /// feature.) - pub bounds: Vec, + pub bounds: Vec>, } /// A single generic argument. diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index a873325b2..cf4e7c02e 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs @@ -171,7 +171,9 @@ pub(super) fn lower_generic_args( let name = name_ref.as_name(); let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { - l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() + l.bounds() + .map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))) + .collect() } else { Vec::new() }; diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index cdcab7110..cbde6b940 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs @@ -5,7 +5,7 @@ use hir_expand::{name::Name, AstId, InFile}; use std::convert::TryInto; use syntax::ast; -use crate::{body::LowerCtx, path::Path}; +use crate::{body::LowerCtx, intern::Interned, path::Path}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Mutability { @@ -91,8 +91,8 @@ pub enum TypeRef { /// A fn pointer. Last element of the vector is the return type. Fn(Vec, bool /*varargs*/), // For - ImplTrait(Vec), - DynTrait(Vec), + ImplTrait(Vec>), + DynTrait(Vec>), Macro(AstId), Error, } @@ -232,7 +232,7 @@ impl TypeRef { | TypeRef::Slice(type_ref) => go(&type_ref, f), TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { for bound in bounds { - match bound { + match bound.as_ref() { TypeBound::Path(path) => go_path(path, f), TypeBound::Lifetime(_) | TypeBound::Error => (), } @@ -262,7 +262,7 @@ impl TypeRef { go(type_ref, f); } for bound in &binding.bounds { - match bound { + match bound.as_ref() { TypeBound::Path(path) => go_path(path, f), TypeBound::Lifetime(_) | TypeBound::Error => (), } @@ -277,9 +277,9 @@ impl TypeRef { pub(crate) fn type_bounds_from_ast( lower_ctx: &LowerCtx, type_bounds_opt: Option, -) -> Vec { +) -> Vec> { if let Some(type_bounds) = type_bounds_opt { - type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() + type_bounds.bounds().map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))).collect() } else { vec![] } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 7bbd1a1f7..637bbc634 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -13,6 +13,7 @@ use hir_def::{ db::DefDatabase, find_path, generics::TypeParamProvenance, + intern::{Internable, Interned}, item_scope::ItemInNs, path::{Path, PathKind}, type_ref::{TypeBound, TypeRef}, @@ -256,6 +257,12 @@ impl HirDisplay for &'_ T { } } +impl HirDisplay for Interned { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + HirDisplay::hir_fmt(self.as_ref(), f) + } +} + impl HirDisplay for ProjectionTy { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { if f.should_truncate() { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 8a375b973..1645ac533 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -10,6 +10,7 @@ use std::{iter, sync::Arc}; use base_db::CrateId; use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; +use hir_def::intern::Interned; use hir_def::{ adt::StructKind, body::{Expander, LowerCtx}, @@ -843,7 +844,7 @@ impl<'a> TyLoweringContext<'a> { }) } - fn lower_impl_trait(&self, bounds: &[TypeBound]) -> ReturnTypeImplTrait { + fn lower_impl_trait(&self, bounds: &[Interned]) -> ReturnTypeImplTrait { cov_mark::hit!(lower_rpit); let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); -- cgit v1.2.3 From 533e9207d39c27dc22de2645fc65891189a71739 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 24 May 2021 15:35:46 +0200 Subject: Intern `GenericArgs` This shaves off another ~4 mb or so --- crates/hir_def/src/intern.rs | 1 + crates/hir_def/src/item_tree/lower.rs | 2 +- crates/hir_def/src/path.rs | 7 +++---- crates/hir_def/src/path/lower.rs | 11 +++++------ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index 8b3f799e2..1189c9327 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs @@ -218,6 +218,7 @@ impl_internable!( crate::type_ref::TraitRef, crate::type_ref::TypeBound, crate::path::ModPath, + crate::path::GenericArgs, GenericParams, str, ); diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 1a0e54413..b4389371f 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -811,7 +811,7 @@ fn desugar_future_path(orig: TypeRef) -> Path { let binding = AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; last.bindings.push(binding); - generic_args.push(Some(Arc::new(last))); + generic_args.push(Some(Interned::new(last))); Path::from_known_path(path, generic_args) } diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 7bd7d9d4f..45ab9d0ff 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs @@ -4,7 +4,6 @@ mod lower; use std::{ fmt::{self, Display}, iter, - sync::Arc, }; use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef}; @@ -136,7 +135,7 @@ pub struct Path { type_anchor: Option>, mod_path: Interned, /// Invariant: the same len as `self.mod_path.segments` - generic_args: Vec>>, + generic_args: Vec>>, } /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This @@ -185,7 +184,7 @@ impl Path { /// Converts a known mod path to `Path`. pub(crate) fn from_known_path( path: ModPath, - generic_args: Vec>>, + generic_args: Vec>>, ) -> Path { Path { type_anchor: None, mod_path: Interned::new(path), generic_args } } @@ -239,7 +238,7 @@ pub struct PathSegment<'a> { pub struct PathSegments<'a> { segments: &'a [Name], - generic_args: &'a [Option>], + generic_args: &'a [Option>], } impl<'a> PathSegments<'a> { diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index cf4e7c02e..5d5dd9c8f 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs @@ -3,7 +3,6 @@ mod lower_use; use crate::intern::Interned; -use std::sync::Arc; use either::Either; use hir_expand::name::{name, AsName}; @@ -48,7 +47,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option { segment.ret_type(), ) }) - .map(Arc::new); + .map(Interned::new); segments.push(name); generic_args.push(args) } @@ -87,13 +86,13 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option { // Insert the type reference (T in the above example) as Self parameter for the trait let last_segment = generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; - if last_segment.is_none() { - *last_segment = Some(Arc::new(GenericArgs::empty())); + let mut args_inner = match last_segment { + Some(it) => it.as_ref().clone(), + None => GenericArgs::empty(), }; - let args = last_segment.as_mut().unwrap(); - let mut args_inner = Arc::make_mut(args); args_inner.has_self_type = true; args_inner.args.insert(0, GenericArg::Type(self_type)); + *last_segment = Some(Interned::new(args_inner)); } } } -- cgit v1.2.3