Skip to content

Commit a75763c

Browse files
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 <[email protected]>
2 parents 63726a9 + 37ff15a commit a75763c

File tree

9 files changed

+83
-50
lines changed

9 files changed

+83
-50
lines changed

crates/hir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1825,7 +1825,7 @@ impl Type {
18251825
Solution::Unique(s) => s
18261826
.value
18271827
.subst
1828-
.interned()
1828+
.as_slice(&Interner)
18291829
.first()
18301830
.map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
18311831
Solution::Ambig(_) => None,

crates/hir_ty/src/chalk_ext.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl TyExt for Ty {
7575
}
7676
fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
7777
match self.kind(&Interner) {
78-
TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
78+
TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
7979
_ => None,
8080
}
8181
}

crates/hir_ty/src/display.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ impl HirDisplay for ProjectionTy {
265265
write!(f, " as {}", trait_.name)?;
266266
if self.substitution.len(&Interner) > 1 {
267267
write!(f, "<")?;
268-
f.write_joined(&self.substitution.interned()[1..], ", ")?;
268+
f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
269269
write!(f, ">")?;
270270
}
271271
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -416,7 +416,7 @@ impl HirDisplay for Ty {
416416
write!(f, ",)")?;
417417
} else {
418418
write!(f, "(")?;
419-
f.write_joined(&*substs.interned(), ", ")?;
419+
f.write_joined(&*substs.as_slice(&Interner), ", ")?;
420420
write!(f, ")")?;
421421
}
422422
}
@@ -444,7 +444,7 @@ impl HirDisplay for Ty {
444444
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
445445
if total_len > 0 {
446446
write!(f, "<")?;
447-
f.write_joined(&parameters.interned()[..total_len], ", ")?;
447+
f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
448448
write!(f, ">")?;
449449
}
450450
}
@@ -491,7 +491,7 @@ impl HirDisplay for Ty {
491491
.map(|generic_def_id| f.db.generic_defaults(generic_def_id))
492492
.filter(|defaults| !defaults.is_empty())
493493
{
494-
None => parameters.interned().as_ref(),
494+
None => parameters.as_slice(&Interner),
495495
Some(default_parameters) => {
496496
let mut default_from = 0;
497497
for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -515,11 +515,11 @@ impl HirDisplay for Ty {
515515
}
516516
}
517517
}
518-
&parameters.interned()[0..default_from]
518+
&parameters.as_slice(&Interner)[0..default_from]
519519
}
520520
}
521521
} else {
522-
parameters.interned().as_ref()
522+
parameters.as_slice(&Interner)
523523
};
524524
if !parameters_to_write.is_empty() {
525525
write!(f, "<")?;
@@ -542,7 +542,7 @@ impl HirDisplay for Ty {
542542
write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
543543
if parameters.len(&Interner) > 0 {
544544
write!(f, "<")?;
545-
f.write_joined(&*parameters.interned(), ", ")?;
545+
f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
546546
write!(f, ">")?;
547547
}
548548
} else {
@@ -749,13 +749,13 @@ fn write_bounds_like_dyn_trait(
749749
// existential) here, which is the only thing that's
750750
// possible in actual Rust, and hence don't print it
751751
write!(f, "{}", f.db.trait_data(trait_).name)?;
752-
if let [_, params @ ..] = &*trait_ref.substitution.interned().as_slice() {
752+
if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
753753
if is_fn_trait {
754754
if let Some(args) =
755755
params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
756756
{
757757
write!(f, "(")?;
758-
f.write_joined(&*args.interned(), ", ")?;
758+
f.write_joined(args.as_slice(&Interner), ", ")?;
759759
write!(f, ")")?;
760760
}
761761
} else if !params.is_empty() {
@@ -814,7 +814,7 @@ fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<()
814814
write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
815815
if tr.substitution.len(&Interner) > 1 {
816816
write!(f, "<")?;
817-
f.write_joined(&tr.substitution.interned()[1..], ", ")?;
817+
f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
818818
write!(f, ">")?;
819819
}
820820
Ok(())

crates/hir_ty/src/infer/expr.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,11 @@ impl<'a> InferenceContext<'a> {
462462
};
463463
match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
464464
TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
465-
substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
465+
substs
466+
.as_slice(&Interner)
467+
.get(idx)
468+
.map(|a| a.assert_ty_ref(&Interner))
469+
.cloned()
466470
}),
467471
TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
468472
let local_id = self.db.struct_data(*s).variant_data.field(name)?;

crates/hir_ty/src/infer/pat.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<'a> InferenceContext<'a> {
122122
let ty = match &body[pat] {
123123
&Pat::Tuple { ref args, ellipsis } => {
124124
let expectations = match expected.as_tuple() {
125-
Some(parameters) => &*parameters.interned().as_slice(),
125+
Some(parameters) => &*parameters.as_slice(&Interner),
126126
_ => &[],
127127
};
128128

@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242242
let (inner_ty, alloc_ty) = match expected.as_adt() {
243243
Some((adt, subst)) if adt == box_adt => (
244244
subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
245-
subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()),
245+
subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
246246
),
247247
_ => (self.result.standard_types.unknown.clone(), None),
248248
};

crates/hir_ty/src/infer/path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> {
101101
let substs = ctx.substs_from_path(path, typable, true);
102102
let ty = TyBuilder::value_ty(self.db, typable)
103103
.use_parent_substs(&parent_substs)
104-
.fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned())
104+
.fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned())
105105
.build();
106106
Some(ty)
107107
}

crates/hir_ty/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub type WhereClause = chalk_ir::WhereClause<Interner>;
109109
pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
110110
Substitution::from_iter(
111111
&Interner,
112-
s.interned()[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
112+
s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
113113
)
114114
}
115115

@@ -187,7 +187,7 @@ impl CallableSig {
187187
.shifted_out_to(&Interner, DebruijnIndex::ONE)
188188
.expect("unexpected lifetime vars in fn ptr")
189189
.0
190-
.interned()
190+
.as_slice(&Interner)
191191
.iter()
192192
.map(|arg| arg.assert_ty_ref(&Interner).clone())
193193
.collect(),

crates/hir_ty/src/traits/chalk/interner.rs

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
//! representation of the various objects Chalk deals with (types, goals etc.).
33
44
use super::tls;
5+
use crate::GenericArg;
56
use base_db::salsa::InternId;
6-
use chalk_ir::{GenericArg, Goal, GoalData};
7-
use hir_def::TypeAliasId;
7+
use chalk_ir::{Goal, GoalData};
8+
use hir_def::{
9+
intern::{impl_internable, InternStorage, Internable, Interned},
10+
TypeAliasId,
11+
};
812
use smallvec::SmallVec;
913
use std::{fmt, sync::Arc};
1014

@@ -26,22 +30,47 @@ pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
2630
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
2731
pub(crate) type Variances = chalk_ir::Variances<Interner>;
2832

33+
#[derive(PartialEq, Eq, Hash, Debug)]
34+
pub struct InternedWrapper<T>(T);
35+
36+
impl<T> std::ops::Deref for InternedWrapper<T> {
37+
type Target = T;
38+
39+
fn deref(&self) -> &Self::Target {
40+
&self.0
41+
}
42+
}
43+
44+
impl_internable!(
45+
InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>,
46+
InternedWrapper<SmallVec<[GenericArg; 2]>>,
47+
InternedWrapper<chalk_ir::TyData<Interner>>,
48+
InternedWrapper<chalk_ir::LifetimeData<Interner>>,
49+
InternedWrapper<chalk_ir::ConstData<Interner>>,
50+
InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
51+
InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
52+
InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
53+
InternedWrapper<Vec<chalk_ir::Variance>>,
54+
);
55+
2956
impl chalk_ir::interner::Interner for Interner {
30-
type InternedType = Arc<chalk_ir::TyData<Self>>;
31-
type InternedLifetime = chalk_ir::LifetimeData<Self>;
32-
type InternedConst = Arc<chalk_ir::ConstData<Self>>;
57+
type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
58+
type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
59+
type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
3360
type InternedConcreteConst = ();
3461
type InternedGenericArg = chalk_ir::GenericArgData<Self>;
3562
type InternedGoal = Arc<GoalData<Self>>;
3663
type InternedGoals = Vec<Goal<Self>>;
37-
type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>;
38-
type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
39-
type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
40-
type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
41-
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
42-
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
64+
type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
65+
type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
66+
type InternedProgramClauses = Interned<InternedWrapper<Vec<chalk_ir::ProgramClause<Self>>>>;
67+
type InternedQuantifiedWhereClauses =
68+
Interned<InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Self>>>>;
69+
type InternedVariableKinds = Interned<InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>>;
70+
type InternedCanonicalVarKinds =
71+
Interned<InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Self>>>>;
4372
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
44-
type InternedVariances = Arc<[chalk_ir::Variance]>;
73+
type InternedVariances = Interned<InternedWrapper<Vec<chalk_ir::Variance>>>;
4574
type DefId = InternId;
4675
type InternedAdtId = hir_def::AdtId;
4776
type Identifier = TypeAliasId;
@@ -99,7 +128,7 @@ impl chalk_ir::interner::Interner for Interner {
99128
}
100129

101130
fn debug_generic_arg(
102-
parameter: &GenericArg<Interner>,
131+
parameter: &GenericArg,
103132
fmt: &mut fmt::Formatter<'_>,
104133
) -> Option<fmt::Result> {
105134
tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
@@ -194,30 +223,30 @@ impl chalk_ir::interner::Interner for Interner {
194223

195224
fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
196225
let flags = kind.compute_flags(self);
197-
Arc::new(chalk_ir::TyData { kind, flags })
226+
Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags }))
198227
}
199228

200229
fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
201-
ty
230+
&ty.0
202231
}
203232

204233
fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
205-
lifetime
234+
Interned::new(InternedWrapper(lifetime))
206235
}
207236

208237
fn lifetime_data<'a>(
209238
&self,
210239
lifetime: &'a Self::InternedLifetime,
211240
) -> &'a chalk_ir::LifetimeData<Self> {
212-
lifetime
241+
&lifetime.0
213242
}
214243

215244
fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
216-
Arc::new(constant)
245+
Interned::new(InternedWrapper(constant))
217246
}
218247

219248
fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
220-
constant
249+
&constant.0
221250
}
222251

223252
fn const_eq(
@@ -264,23 +293,23 @@ impl chalk_ir::interner::Interner for Interner {
264293

265294
fn intern_substitution<E>(
266295
&self,
267-
data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>,
296+
data: impl IntoIterator<Item = Result<GenericArg, E>>,
268297
) -> Result<Self::InternedSubstitution, E> {
269-
data.into_iter().collect()
298+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
270299
}
271300

272301
fn substitution_data<'a>(
273302
&self,
274303
substitution: &'a Self::InternedSubstitution,
275-
) -> &'a [GenericArg<Self>] {
276-
substitution
304+
) -> &'a [GenericArg] {
305+
&substitution.as_ref().0
277306
}
278307

279308
fn intern_program_clause(
280309
&self,
281310
data: chalk_ir::ProgramClauseData<Self>,
282311
) -> Self::InternedProgramClause {
283-
Arc::new(data)
312+
data
284313
}
285314

286315
fn program_clause_data<'a>(
@@ -294,7 +323,7 @@ impl chalk_ir::interner::Interner for Interner {
294323
&self,
295324
data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
296325
) -> Result<Self::InternedProgramClauses, E> {
297-
data.into_iter().collect()
326+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
298327
}
299328

300329
fn program_clauses_data<'a>(
@@ -308,7 +337,7 @@ impl chalk_ir::interner::Interner for Interner {
308337
&self,
309338
data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
310339
) -> Result<Self::InternedQuantifiedWhereClauses, E> {
311-
data.into_iter().collect()
340+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
312341
}
313342

314343
fn quantified_where_clauses_data<'a>(
@@ -322,21 +351,21 @@ impl chalk_ir::interner::Interner for Interner {
322351
&self,
323352
data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
324353
) -> Result<Self::InternedVariableKinds, E> {
325-
data.into_iter().collect()
354+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
326355
}
327356

328357
fn variable_kinds_data<'a>(
329358
&self,
330359
parameter_kinds: &'a Self::InternedVariableKinds,
331360
) -> &'a [chalk_ir::VariableKind<Self>] {
332-
&parameter_kinds
361+
&parameter_kinds.as_ref().0
333362
}
334363

335364
fn intern_canonical_var_kinds<E>(
336365
&self,
337366
data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
338367
) -> Result<Self::InternedCanonicalVarKinds, E> {
339-
data.into_iter().collect()
368+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
340369
}
341370

342371
fn canonical_var_kinds_data<'a>(
@@ -376,7 +405,7 @@ impl chalk_ir::interner::Interner for Interner {
376405
&self,
377406
data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
378407
) -> Result<Self::InternedVariances, E> {
379-
data.into_iter().collect()
408+
Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
380409
}
381410

382411
fn variances_data<'a>(

crates/hir_ty/src/traits/chalk/mapping.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub(super) fn generic_predicate_to_inline_bound(
9999
// have the expected self type
100100
return None;
101101
}
102-
let args_no_self = trait_ref.substitution.interned()[1..]
102+
let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
103103
.iter()
104104
.map(|ty| ty.clone().cast(&Interner))
105105
.collect();
@@ -111,7 +111,7 @@ pub(super) fn generic_predicate_to_inline_bound(
111111
return None;
112112
}
113113
let trait_ = projection_ty.trait_(db);
114-
let args_no_self = projection_ty.substitution.interned()[1..]
114+
let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
115115
.iter()
116116
.map(|ty| ty.clone().cast(&Interner))
117117
.collect();

0 commit comments

Comments
 (0)