Merge #8433
8433: Intern lots of things r=jonas-schievink a=flodiebold This uses the new interning infrastructure for most type-related things, where it had a positive effect on memory usage and performance. In total, this gives a slight performance improvement and a quite good memory reduction (1119MB->885MB on RA, 1774MB->1188MB on Diesel). Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
a75763cd57
@ -1825,7 +1825,7 @@ impl Type {
|
||||
Solution::Unique(s) => s
|
||||
.value
|
||||
.subst
|
||||
.interned()
|
||||
.as_slice(&Interner)
|
||||
.first()
|
||||
.map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
|
||||
Solution::Ambig(_) => None,
|
||||
|
@ -75,7 +75,7 @@ impl TyExt for Ty {
|
||||
}
|
||||
fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
|
||||
match self.kind(&Interner) {
|
||||
TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
|
||||
TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ impl HirDisplay for ProjectionTy {
|
||||
write!(f, " as {}", trait_.name)?;
|
||||
if self.substitution.len(&Interner) > 1 {
|
||||
write!(f, "<")?;
|
||||
f.write_joined(&self.substitution.interned()[1..], ", ")?;
|
||||
f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
|
||||
@ -416,7 +416,7 @@ impl HirDisplay for Ty {
|
||||
write!(f, ",)")?;
|
||||
} else {
|
||||
write!(f, "(")?;
|
||||
f.write_joined(&*substs.interned(), ", ")?;
|
||||
f.write_joined(&*substs.as_slice(&Interner), ", ")?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
}
|
||||
@ -444,7 +444,7 @@ impl HirDisplay for Ty {
|
||||
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
|
||||
if total_len > 0 {
|
||||
write!(f, "<")?;
|
||||
f.write_joined(¶meters.interned()[..total_len], ", ")?;
|
||||
f.write_joined(¶meters.as_slice(&Interner)[..total_len], ", ")?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
}
|
||||
@ -491,7 +491,7 @@ impl HirDisplay for Ty {
|
||||
.map(|generic_def_id| f.db.generic_defaults(generic_def_id))
|
||||
.filter(|defaults| !defaults.is_empty())
|
||||
{
|
||||
None => parameters.interned().as_ref(),
|
||||
None => parameters.as_slice(&Interner),
|
||||
Some(default_parameters) => {
|
||||
let mut default_from = 0;
|
||||
for (i, parameter) in parameters.iter(&Interner).enumerate() {
|
||||
@ -515,11 +515,11 @@ impl HirDisplay for Ty {
|
||||
}
|
||||
}
|
||||
}
|
||||
¶meters.interned()[0..default_from]
|
||||
¶meters.as_slice(&Interner)[0..default_from]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parameters.interned().as_ref()
|
||||
parameters.as_slice(&Interner)
|
||||
};
|
||||
if !parameters_to_write.is_empty() {
|
||||
write!(f, "<")?;
|
||||
@ -542,7 +542,7 @@ impl HirDisplay for Ty {
|
||||
write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
|
||||
if parameters.len(&Interner) > 0 {
|
||||
write!(f, "<")?;
|
||||
f.write_joined(&*parameters.interned(), ", ")?;
|
||||
f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
} else {
|
||||
@ -749,13 +749,13 @@ fn write_bounds_like_dyn_trait(
|
||||
// existential) here, which is the only thing that's
|
||||
// possible in actual Rust, and hence don't print it
|
||||
write!(f, "{}", f.db.trait_data(trait_).name)?;
|
||||
if let [_, params @ ..] = &*trait_ref.substitution.interned().as_slice() {
|
||||
if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
|
||||
if is_fn_trait {
|
||||
if let Some(args) =
|
||||
params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
|
||||
{
|
||||
write!(f, "(")?;
|
||||
f.write_joined(&*args.interned(), ", ")?;
|
||||
f.write_joined(args.as_slice(&Interner), ", ")?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
} else if !params.is_empty() {
|
||||
@ -814,7 +814,7 @@ fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<()
|
||||
write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
|
||||
if tr.substitution.len(&Interner) > 1 {
|
||||
write!(f, "<")?;
|
||||
f.write_joined(&tr.substitution.interned()[1..], ", ")?;
|
||||
f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -462,7 +462,11 @@ impl<'a> InferenceContext<'a> {
|
||||
};
|
||||
match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
|
||||
TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
|
||||
substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
|
||||
substs
|
||||
.as_slice(&Interner)
|
||||
.get(idx)
|
||||
.map(|a| a.assert_ty_ref(&Interner))
|
||||
.cloned()
|
||||
}),
|
||||
TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
|
||||
let local_id = self.db.struct_data(*s).variant_data.field(name)?;
|
||||
|
@ -122,7 +122,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let ty = match &body[pat] {
|
||||
&Pat::Tuple { ref args, ellipsis } => {
|
||||
let expectations = match expected.as_tuple() {
|
||||
Some(parameters) => &*parameters.interned().as_slice(),
|
||||
Some(parameters) => &*parameters.as_slice(&Interner),
|
||||
_ => &[],
|
||||
};
|
||||
|
||||
@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let (inner_ty, alloc_ty) = match expected.as_adt() {
|
||||
Some((adt, subst)) if adt == box_adt => (
|
||||
subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
|
||||
subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()),
|
||||
subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
|
||||
),
|
||||
_ => (self.result.standard_types.unknown.clone(), None),
|
||||
};
|
||||
|
@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> {
|
||||
let substs = ctx.substs_from_path(path, typable, true);
|
||||
let ty = TyBuilder::value_ty(self.db, typable)
|
||||
.use_parent_substs(&parent_substs)
|
||||
.fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned())
|
||||
.fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned())
|
||||
.build();
|
||||
Some(ty)
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ pub type WhereClause = chalk_ir::WhereClause<Interner>;
|
||||
pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
|
||||
Substitution::from_iter(
|
||||
&Interner,
|
||||
s.interned()[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
|
||||
s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ impl CallableSig {
|
||||
.shifted_out_to(&Interner, DebruijnIndex::ONE)
|
||||
.expect("unexpected lifetime vars in fn ptr")
|
||||
.0
|
||||
.interned()
|
||||
.as_slice(&Interner)
|
||||
.iter()
|
||||
.map(|arg| arg.assert_ty_ref(&Interner).clone())
|
||||
.collect(),
|
||||
|
@ -2,9 +2,13 @@
|
||||
//! representation of the various objects Chalk deals with (types, goals etc.).
|
||||
|
||||
use super::tls;
|
||||
use crate::GenericArg;
|
||||
use base_db::salsa::InternId;
|
||||
use chalk_ir::{GenericArg, Goal, GoalData};
|
||||
use hir_def::TypeAliasId;
|
||||
use chalk_ir::{Goal, GoalData};
|
||||
use hir_def::{
|
||||
intern::{impl_internable, InternStorage, Internable, Interned},
|
||||
TypeAliasId,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{fmt, sync::Arc};
|
||||
|
||||
@ -26,22 +30,47 @@ pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
|
||||
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
|
||||
pub(crate) type Variances = chalk_ir::Variances<Interner>;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub struct InternedWrapper<T>(T);
|
||||
|
||||
impl<T> std::ops::Deref for InternedWrapper<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl_internable!(
|
||||
InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>,
|
||||
InternedWrapper<SmallVec<[GenericArg; 2]>>,
|
||||
InternedWrapper<chalk_ir::TyData<Interner>>,
|
||||
InternedWrapper<chalk_ir::LifetimeData<Interner>>,
|
||||
InternedWrapper<chalk_ir::ConstData<Interner>>,
|
||||
InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
|
||||
InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
|
||||
InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
|
||||
InternedWrapper<Vec<chalk_ir::Variance>>,
|
||||
);
|
||||
|
||||
impl chalk_ir::interner::Interner for Interner {
|
||||
type InternedType = Arc<chalk_ir::TyData<Self>>;
|
||||
type InternedLifetime = chalk_ir::LifetimeData<Self>;
|
||||
type InternedConst = Arc<chalk_ir::ConstData<Self>>;
|
||||
type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
|
||||
type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
|
||||
type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
|
||||
type InternedConcreteConst = ();
|
||||
type InternedGenericArg = chalk_ir::GenericArgData<Self>;
|
||||
type InternedGoal = Arc<GoalData<Self>>;
|
||||
type InternedGoals = Vec<Goal<Self>>;
|
||||
type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>;
|
||||
type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
|
||||
type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
|
||||
type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
|
||||
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
|
||||
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
|
||||
type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
|
||||
type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
|
||||
type InternedProgramClauses = Interned<InternedWrapper<Vec<chalk_ir::ProgramClause<Self>>>>;
|
||||
type InternedQuantifiedWhereClauses =
|
||||
Interned<InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Self>>>>;
|
||||
type InternedVariableKinds = Interned<InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>>;
|
||||
type InternedCanonicalVarKinds =
|
||||
Interned<InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Self>>>>;
|
||||
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
|
||||
type InternedVariances = Arc<[chalk_ir::Variance]>;
|
||||
type InternedVariances = Interned<InternedWrapper<Vec<chalk_ir::Variance>>>;
|
||||
type DefId = InternId;
|
||||
type InternedAdtId = hir_def::AdtId;
|
||||
type Identifier = TypeAliasId;
|
||||
@ -99,7 +128,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
}
|
||||
|
||||
fn debug_generic_arg(
|
||||
parameter: &GenericArg<Interner>,
|
||||
parameter: &GenericArg,
|
||||
fmt: &mut fmt::Formatter<'_>,
|
||||
) -> Option<fmt::Result> {
|
||||
tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
|
||||
@ -194,30 +223,30 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
|
||||
fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
|
||||
let flags = kind.compute_flags(self);
|
||||
Arc::new(chalk_ir::TyData { kind, flags })
|
||||
Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags }))
|
||||
}
|
||||
|
||||
fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
|
||||
ty
|
||||
&ty.0
|
||||
}
|
||||
|
||||
fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
|
||||
lifetime
|
||||
Interned::new(InternedWrapper(lifetime))
|
||||
}
|
||||
|
||||
fn lifetime_data<'a>(
|
||||
&self,
|
||||
lifetime: &'a Self::InternedLifetime,
|
||||
) -> &'a chalk_ir::LifetimeData<Self> {
|
||||
lifetime
|
||||
&lifetime.0
|
||||
}
|
||||
|
||||
fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
|
||||
Arc::new(constant)
|
||||
Interned::new(InternedWrapper(constant))
|
||||
}
|
||||
|
||||
fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
|
||||
constant
|
||||
&constant.0
|
||||
}
|
||||
|
||||
fn const_eq(
|
||||
@ -264,23 +293,23 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
|
||||
fn intern_substitution<E>(
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>,
|
||||
data: impl IntoIterator<Item = Result<GenericArg, E>>,
|
||||
) -> Result<Self::InternedSubstitution, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn substitution_data<'a>(
|
||||
&self,
|
||||
substitution: &'a Self::InternedSubstitution,
|
||||
) -> &'a [GenericArg<Self>] {
|
||||
substitution
|
||||
) -> &'a [GenericArg] {
|
||||
&substitution.as_ref().0
|
||||
}
|
||||
|
||||
fn intern_program_clause(
|
||||
&self,
|
||||
data: chalk_ir::ProgramClauseData<Self>,
|
||||
) -> Self::InternedProgramClause {
|
||||
Arc::new(data)
|
||||
data
|
||||
}
|
||||
|
||||
fn program_clause_data<'a>(
|
||||
@ -294,7 +323,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
|
||||
) -> Result<Self::InternedProgramClauses, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn program_clauses_data<'a>(
|
||||
@ -308,7 +337,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
|
||||
) -> Result<Self::InternedQuantifiedWhereClauses, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn quantified_where_clauses_data<'a>(
|
||||
@ -322,21 +351,21 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
|
||||
) -> Result<Self::InternedVariableKinds, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn variable_kinds_data<'a>(
|
||||
&self,
|
||||
parameter_kinds: &'a Self::InternedVariableKinds,
|
||||
) -> &'a [chalk_ir::VariableKind<Self>] {
|
||||
¶meter_kinds
|
||||
¶meter_kinds.as_ref().0
|
||||
}
|
||||
|
||||
fn intern_canonical_var_kinds<E>(
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
|
||||
) -> Result<Self::InternedCanonicalVarKinds, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn canonical_var_kinds_data<'a>(
|
||||
@ -376,7 +405,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
&self,
|
||||
data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
|
||||
) -> Result<Self::InternedVariances, E> {
|
||||
data.into_iter().collect()
|
||||
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
|
||||
}
|
||||
|
||||
fn variances_data<'a>(
|
||||
|
@ -99,7 +99,7 @@ pub(super) fn generic_predicate_to_inline_bound(
|
||||
// have the expected self type
|
||||
return None;
|
||||
}
|
||||
let args_no_self = trait_ref.substitution.interned()[1..]
|
||||
let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
|
||||
.iter()
|
||||
.map(|ty| ty.clone().cast(&Interner))
|
||||
.collect();
|
||||
@ -111,7 +111,7 @@ pub(super) fn generic_predicate_to_inline_bound(
|
||||
return None;
|
||||
}
|
||||
let trait_ = projection_ty.trait_(db);
|
||||
let args_no_self = projection_ty.substitution.interned()[1..]
|
||||
let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
|
||||
.iter()
|
||||
.map(|ty| ty.clone().cast(&Interner))
|
||||
.collect();
|
||||
|
Loading…
x
Reference in New Issue
Block a user