mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
internal: intern TypeBound
s
Doesn't save much memory (~2 mb), but interning things is generally a good pattern to follow
This commit is contained in:
parent
05fc97e31b
commit
8ebb8d29e1
12 changed files with 49 additions and 27 deletions
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)) => {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}}"),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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()
|
||||||
};
|
};
|
||||||
|
|
|
@ -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![]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue