internal: intern TypeBounds

Doesn't save much memory (~2 mb), but interning things is generally a
good pattern to follow
This commit is contained in:
Jonas Schievink 2021-05-24 15:13:23 +02:00
parent 05fc97e31b
commit 8ebb8d29e1
12 changed files with 49 additions and 27 deletions

View file

@ -92,7 +92,7 @@ impl HirDisplay for Function {
&data.ret_type &data.ret_type
} else { } else {
match &*data.ret_type { match &*data.ret_type {
TypeRef::ImplTrait(bounds) => match &bounds[0] { TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
TypeBound::Path(path) => { TypeBound::Path(path) => {
path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
[0] [0]

View file

@ -112,7 +112,7 @@ pub struct TypeAliasData {
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub is_extern: bool, pub is_extern: bool,
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
pub bounds: Vec<TypeBound>, pub bounds: Vec<Interned<TypeBound>>,
} }
impl TypeAliasData { impl TypeAliasData {
@ -141,7 +141,7 @@ pub struct TraitData {
pub is_auto: bool, pub is_auto: bool,
pub is_unsafe: bool, pub is_unsafe: bool,
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub bounds: Box<[TypeBound]>, pub bounds: Box<[Interned<TypeBound>]>,
} }
impl TraitData { impl TraitData {

View file

@ -68,9 +68,19 @@ pub struct GenericParams {
/// associated type bindings like `Iterator<Item = u32>`. /// associated type bindings like `Iterator<Item = u32>`.
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum WherePredicate { pub enum WherePredicate {
TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, TypeBound {
Lifetime { target: LifetimeRef, bound: LifetimeRef }, target: WherePredicateTypeTarget,
ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, bound: Interned<TypeBound>,
},
Lifetime {
target: LifetimeRef,
bound: LifetimeRef,
},
ForLifetime {
lifetimes: Box<[Name]>,
target: WherePredicateTypeTarget,
bound: Interned<TypeBound>,
},
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@ -339,11 +349,11 @@ impl GenericParams {
Some(hrtb_lifetimes) => WherePredicate::ForLifetime { Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
lifetimes: hrtb_lifetimes.clone(), lifetimes: hrtb_lifetimes.clone(),
target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
bound, bound: Interned::new(bound),
}, },
None => WherePredicate::TypeBound { None => WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
bound, bound: Interned::new(bound),
}, },
}, },
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => { (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {

View file

@ -216,6 +216,7 @@ pub use crate::_impl_internable as impl_internable;
impl_internable!( impl_internable!(
crate::type_ref::TypeRef, crate::type_ref::TypeRef,
crate::type_ref::TraitRef, crate::type_ref::TraitRef,
crate::type_ref::TypeBound,
crate::path::ModPath, crate::path::ModPath,
GenericParams, GenericParams,
str, str,

View file

@ -644,7 +644,7 @@ pub struct Trait {
pub generic_params: Interned<GenericParams>, pub generic_params: Interned<GenericParams>,
pub is_auto: bool, pub is_auto: bool,
pub is_unsafe: bool, pub is_unsafe: bool,
pub bounds: Box<[TypeBound]>, pub bounds: Box<[Interned<TypeBound>]>,
pub items: Box<[AssocItem]>, pub items: Box<[AssocItem]>,
pub ast_id: FileAstId<ast::Trait>, pub ast_id: FileAstId<ast::Trait>,
} }
@ -664,7 +664,7 @@ pub struct TypeAlias {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
/// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
pub bounds: Box<[TypeBound]>, pub bounds: Box<[Interned<TypeBound>]>,
pub generic_params: Interned<GenericParams>, pub generic_params: Interned<GenericParams>,
pub type_ref: Option<Interned<TypeRef>>, pub type_ref: Option<Interned<TypeRef>>,
pub is_extern: bool, pub is_extern: bool,

View file

@ -384,7 +384,7 @@ impl<'a> Ctx<'a> {
let ret_type = if func.async_token().is_some() { let ret_type = if func.async_token().is_some() {
let future_impl = desugar_future_path(ret_type); 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]) TypeRef::ImplTrait(vec![ty_bound])
} else { } else {
ret_type ret_type
@ -738,11 +738,12 @@ impl<'a> Ctx<'a> {
Interned::new(generics) Interned::new(generics)
} }
fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<Interned<TypeBound>> {
match node.type_bound_list() { match node.type_bound_list() {
Some(bound_list) => { Some(bound_list) => bound_list
bound_list.bounds().map(|it| TypeBound::from_ast(&self.body_ctx, it)).collect() .bounds()
} .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it)))
.collect(),
None => Vec::new(), None => Vec::new(),
} }
} }

View file

@ -513,13 +513,13 @@ impl<'a> Printer<'a> {
} }
} }
fn print_type_bounds(&mut self, bounds: &[TypeBound]) { fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) {
for (i, bound) in bounds.iter().enumerate() { for (i, bound) in bounds.iter().enumerate() {
if i != 0 { if i != 0 {
w!(self, " + "); w!(self, " + ");
} }
match bound { match bound.as_ref() {
TypeBound::Path(path) => self.print_path(path), TypeBound::Path(path) => self.print_path(path),
TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
TypeBound::Error => w!(self, "{{unknown}}"), TypeBound::Error => w!(self, "{{unknown}}"),

View file

@ -165,7 +165,7 @@ pub struct AssociatedTypeBinding {
/// Bounds for the associated type, like in `Iterator<Item: /// Bounds for the associated type, like in `Iterator<Item:
/// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
/// feature.) /// feature.)
pub bounds: Vec<TypeBound>, pub bounds: Vec<Interned<TypeBound>>,
} }
/// A single generic argument. /// A single generic argument.

View file

@ -171,7 +171,9 @@ pub(super) fn lower_generic_args(
let name = name_ref.as_name(); let name = name_ref.as_name();
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); 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() { 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 { } else {
Vec::new() Vec::new()
}; };

View file

@ -5,7 +5,7 @@ use hir_expand::{name::Name, AstId, InFile};
use std::convert::TryInto; use std::convert::TryInto;
use syntax::ast; use syntax::ast;
use crate::{body::LowerCtx, path::Path}; use crate::{body::LowerCtx, intern::Interned, path::Path};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum Mutability { pub enum Mutability {
@ -91,8 +91,8 @@ pub enum TypeRef {
/// A fn pointer. Last element of the vector is the return type. /// A fn pointer. Last element of the vector is the return type.
Fn(Vec<TypeRef>, bool /*varargs*/), Fn(Vec<TypeRef>, bool /*varargs*/),
// For // For
ImplTrait(Vec<TypeBound>), ImplTrait(Vec<Interned<TypeBound>>),
DynTrait(Vec<TypeBound>), DynTrait(Vec<Interned<TypeBound>>),
Macro(AstId<ast::MacroCall>), Macro(AstId<ast::MacroCall>),
Error, Error,
} }
@ -232,7 +232,7 @@ impl TypeRef {
| TypeRef::Slice(type_ref) => go(&type_ref, f), | TypeRef::Slice(type_ref) => go(&type_ref, f),
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
for bound in bounds { for bound in bounds {
match bound { match bound.as_ref() {
TypeBound::Path(path) => go_path(path, f), TypeBound::Path(path) => go_path(path, f),
TypeBound::Lifetime(_) | TypeBound::Error => (), TypeBound::Lifetime(_) | TypeBound::Error => (),
} }
@ -262,7 +262,7 @@ impl TypeRef {
go(type_ref, f); go(type_ref, f);
} }
for bound in &binding.bounds { for bound in &binding.bounds {
match bound { match bound.as_ref() {
TypeBound::Path(path) => go_path(path, f), TypeBound::Path(path) => go_path(path, f),
TypeBound::Lifetime(_) | TypeBound::Error => (), TypeBound::Lifetime(_) | TypeBound::Error => (),
} }
@ -277,9 +277,9 @@ impl TypeRef {
pub(crate) fn type_bounds_from_ast( pub(crate) fn type_bounds_from_ast(
lower_ctx: &LowerCtx, lower_ctx: &LowerCtx,
type_bounds_opt: Option<ast::TypeBoundList>, type_bounds_opt: Option<ast::TypeBoundList>,
) -> Vec<TypeBound> { ) -> Vec<Interned<TypeBound>> {
if let Some(type_bounds) = type_bounds_opt { 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 { } else {
vec![] vec![]
} }

View file

@ -13,6 +13,7 @@ use hir_def::{
db::DefDatabase, db::DefDatabase,
find_path, find_path,
generics::TypeParamProvenance, generics::TypeParamProvenance,
intern::{Internable, Interned},
item_scope::ItemInNs, item_scope::ItemInNs,
path::{Path, PathKind}, path::{Path, PathKind},
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef},
@ -256,6 +257,12 @@ impl<T: HirDisplay> HirDisplay for &'_ T {
} }
} }
impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
HirDisplay::hir_fmt(self.as_ref(), f)
}
}
impl HirDisplay for ProjectionTy { impl HirDisplay for ProjectionTy {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
if f.should_truncate() { if f.should_truncate() {

View file

@ -10,6 +10,7 @@ use std::{iter, sync::Arc};
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
use hir_def::intern::Interned;
use hir_def::{ use hir_def::{
adt::StructKind, adt::StructKind,
body::{Expander, LowerCtx}, 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<TypeBound>]) -> ReturnTypeImplTrait {
cov_mark::hit!(lower_rpit); cov_mark::hit!(lower_rpit);
let self_ty = let self_ty =
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);