aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-04-08 17:25:18 +0100
committerFlorian Diebold <[email protected]>2021-04-08 21:48:47 +0100
commitbe03db0e3a75533f34d48c3014d532919b30a9e9 (patch)
tree3742a817b8238043a3a855d92532c7342815210e
parenta169fa6a832a513cd1534d1a6566e4584ca5fb6a (diff)
Intern Substitutions
(Costs a bit of performance, reduces memory usage on RA by ~10%.)
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir_ty/src/display.rs20
-rw-r--r--crates/hir_ty/src/infer/expr.rs2
-rw-r--r--crates/hir_ty/src/infer/pat.rs4
-rw-r--r--crates/hir_ty/src/infer/path.rs2
-rw-r--r--crates/hir_ty/src/lib.rs4
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs23
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs4
8 files changed, 34 insertions, 27 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 817a01db1..04875240b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1825,7 +1825,7 @@ impl Type {
1825 Solution::Unique(s) => s 1825 Solution::Unique(s) => s
1826 .value 1826 .value
1827 .subst 1827 .subst
1828 .interned() 1828 .as_slice(&Interner)
1829 .first() 1829 .first()
1830 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), 1830 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1831 Solution::Ambig(_) => None, 1831 Solution::Ambig(_) => None,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index d7a3977e5..92224b46b 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -265,7 +265,7 @@ impl HirDisplay for ProjectionTy {
265 write!(f, " as {}", trait_.name)?; 265 write!(f, " as {}", trait_.name)?;
266 if self.substitution.len(&Interner) > 1 { 266 if self.substitution.len(&Interner) > 1 {
267 write!(f, "<")?; 267 write!(f, "<")?;
268 f.write_joined(&self.substitution.interned()[1..], ", ")?; 268 f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
269 write!(f, ">")?; 269 write!(f, ">")?;
270 } 270 }
271 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 271 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -416,7 +416,7 @@ impl HirDisplay for Ty {
416 write!(f, ",)")?; 416 write!(f, ",)")?;
417 } else { 417 } else {
418 write!(f, "(")?; 418 write!(f, "(")?;
419 f.write_joined(&*substs.interned(), ", ")?; 419 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
420 write!(f, ")")?; 420 write!(f, ")")?;
421 } 421 }
422 } 422 }
@@ -444,7 +444,7 @@ impl HirDisplay for Ty {
444 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 444 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
445 if total_len > 0 { 445 if total_len > 0 {
446 write!(f, "<")?; 446 write!(f, "<")?;
447 f.write_joined(&parameters.interned()[..total_len], ", ")?; 447 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
448 write!(f, ">")?; 448 write!(f, ">")?;
449 } 449 }
450 } 450 }
@@ -491,7 +491,7 @@ impl HirDisplay for Ty {
491 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 491 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
492 .filter(|defaults| !defaults.is_empty()) 492 .filter(|defaults| !defaults.is_empty())
493 { 493 {
494 None => parameters.interned().as_ref(), 494 None => parameters.as_slice(&Interner),
495 Some(default_parameters) => { 495 Some(default_parameters) => {
496 let mut default_from = 0; 496 let mut default_from = 0;
497 for (i, parameter) in parameters.iter(&Interner).enumerate() { 497 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -515,11 +515,11 @@ impl HirDisplay for Ty {
515 } 515 }
516 } 516 }
517 } 517 }
518 &parameters.interned()[0..default_from] 518 &parameters.as_slice(&Interner)[0..default_from]
519 } 519 }
520 } 520 }
521 } else { 521 } else {
522 parameters.interned().as_ref() 522 parameters.as_slice(&Interner)
523 }; 523 };
524 if !parameters_to_write.is_empty() { 524 if !parameters_to_write.is_empty() {
525 write!(f, "<")?; 525 write!(f, "<")?;
@@ -542,7 +542,7 @@ impl HirDisplay for Ty {
542 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 542 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
543 if parameters.len(&Interner) > 0 { 543 if parameters.len(&Interner) > 0 {
544 write!(f, "<")?; 544 write!(f, "<")?;
545 f.write_joined(&*parameters.interned(), ", ")?; 545 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
546 write!(f, ">")?; 546 write!(f, ">")?;
547 } 547 }
548 } else { 548 } else {
@@ -749,13 +749,13 @@ fn write_bounds_like_dyn_trait(
749 // existential) here, which is the only thing that's 749 // existential) here, which is the only thing that's
750 // possible in actual Rust, and hence don't print it 750 // possible in actual Rust, and hence don't print it
751 write!(f, "{}", f.db.trait_data(trait_).name)?; 751 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) {
753 if is_fn_trait { 753 if is_fn_trait {
754 if let Some(args) = 754 if let Some(args) =
755 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 755 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
756 { 756 {
757 write!(f, "(")?; 757 write!(f, "(")?;
758 f.write_joined(&*args.interned(), ", ")?; 758 f.write_joined(args.as_slice(&Interner), ", ")?;
759 write!(f, ")")?; 759 write!(f, ")")?;
760 } 760 }
761 } else if !params.is_empty() { 761 } else if !params.is_empty() {
@@ -814,7 +814,7 @@ fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<()
814 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?; 814 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
815 if tr.substitution.len(&Interner) > 1 { 815 if tr.substitution.len(&Interner) > 1 {
816 write!(f, "<")?; 816 write!(f, "<")?;
817 f.write_joined(&tr.substitution.interned()[1..], ", ")?; 817 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
818 write!(f, ">")?; 818 write!(f, ">")?;
819 } 819 }
820 Ok(()) 820 Ok(())
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index cbbfa8b5c..ee6763926 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -462,7 +462,7 @@ impl<'a> InferenceContext<'a> {
462 }; 462 };
463 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 463 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
464 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 464 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.as_slice(&Interner).get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
466 }), 466 }),
467 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 467 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
468 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 468 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index a41e8e116..aea354cde 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -122,7 +122,7 @@ impl<'a> InferenceContext<'a> {
122 let ty = match &body[pat] { 122 let ty = match &body[pat] {
123 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
124 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
125 Some(parameters) => &*parameters.interned().as_slice(), 125 Some(parameters) => &*parameters.as_slice(&Interner),
126 _ => &[], 126 _ => &[],
127 }; 127 };
128 128
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242 let (inner_ty, alloc_ty) = match expected.as_adt() { 242 let (inner_ty, alloc_ty) = match expected.as_adt() {
243 Some((adt, subst)) if adt == box_adt => ( 243 Some((adt, subst)) if adt == box_adt => (
244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 244 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()),
246 ), 246 ),
247 _ => (self.result.standard_types.unknown.clone(), None), 247 _ => (self.result.standard_types.unknown.clone(), None),
248 }; 248 };
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index f8955aa32..495282eba 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> {
101 let substs = ctx.substs_from_path(path, typable, true); 101 let substs = ctx.substs_from_path(path, typable, true);
102 let ty = TyBuilder::value_ty(self.db, typable) 102 let ty = TyBuilder::value_ty(self.db, typable)
103 .use_parent_substs(&parent_substs) 103 .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())
105 .build(); 105 .build();
106 Some(ty) 106 Some(ty)
107 } 107 }
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 874c95411..beb58d711 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -109,7 +109,7 @@ pub type WhereClause = chalk_ir::WhereClause<Interner>;
109pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution { 109pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
110 Substitution::from_iter( 110 Substitution::from_iter(
111 &Interner, 111 &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(),
113 ) 113 )
114} 114}
115 115
@@ -187,7 +187,7 @@ impl CallableSig {
187 .shifted_out_to(&Interner, DebruijnIndex::ONE) 187 .shifted_out_to(&Interner, DebruijnIndex::ONE)
188 .expect("unexpected lifetime vars in fn ptr") 188 .expect("unexpected lifetime vars in fn ptr")
189 .0 189 .0
190 .interned() 190 .as_slice(&Interner)
191 .iter() 191 .iter()
192 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 192 .map(|arg| arg.assert_ty_ref(&Interner).clone())
193 .collect(), 193 .collect(),
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs
index 7a3bd41d4..17e056f03 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/traits/chalk/interner.rs
@@ -3,11 +3,12 @@
3 3
4use super::tls; 4use super::tls;
5use base_db::salsa::InternId; 5use base_db::salsa::InternId;
6use chalk_ir::{GenericArg, Goal, GoalData}; 6use chalk_ir::{Goal, GoalData};
7use hir_def::{ 7use hir_def::{
8 intern::{impl_internable, InternStorage, Internable, Interned}, 8 intern::{impl_internable, InternStorage, Internable, Interned},
9 TypeAliasId, 9 TypeAliasId,
10}; 10};
11use crate::GenericArg;
11use smallvec::SmallVec; 12use smallvec::SmallVec;
12use std::{fmt, sync::Arc}; 13use std::{fmt, sync::Arc};
13 14
@@ -32,7 +33,13 @@ pub(crate) type Variances = chalk_ir::Variances<Interner>;
32#[derive(PartialEq, Eq, Hash, Debug)] 33#[derive(PartialEq, Eq, Hash, Debug)]
33pub struct InternedVariableKindsInner(Vec<chalk_ir::VariableKind<Interner>>); 34pub struct InternedVariableKindsInner(Vec<chalk_ir::VariableKind<Interner>>);
34 35
35impl_internable!(InternedVariableKindsInner,); 36#[derive(PartialEq, Eq, Hash, Debug)]
37pub struct InternedSubstitutionInner(SmallVec<[GenericArg; 2]>);
38
39impl_internable!(
40 InternedVariableKindsInner,
41 InternedSubstitutionInner,
42);
36 43
37impl chalk_ir::interner::Interner for Interner { 44impl chalk_ir::interner::Interner for Interner {
38 type InternedType = Arc<chalk_ir::TyData<Self>>; 45 type InternedType = Arc<chalk_ir::TyData<Self>>;
@@ -42,7 +49,7 @@ impl chalk_ir::interner::Interner for Interner {
42 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 49 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
43 type InternedGoal = Arc<GoalData<Self>>; 50 type InternedGoal = Arc<GoalData<Self>>;
44 type InternedGoals = Vec<Goal<Self>>; 51 type InternedGoals = Vec<Goal<Self>>;
45 type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>; 52 type InternedSubstitution = Interned<InternedSubstitutionInner>;
46 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>; 53 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>;
47 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; 54 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>;
48 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 55 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
@@ -107,7 +114,7 @@ impl chalk_ir::interner::Interner for Interner {
107 } 114 }
108 115
109 fn debug_generic_arg( 116 fn debug_generic_arg(
110 parameter: &GenericArg<Interner>, 117 parameter: &GenericArg,
111 fmt: &mut fmt::Formatter<'_>, 118 fmt: &mut fmt::Formatter<'_>,
112 ) -> Option<fmt::Result> { 119 ) -> Option<fmt::Result> {
113 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) 120 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
@@ -272,16 +279,16 @@ impl chalk_ir::interner::Interner for Interner {
272 279
273 fn intern_substitution<E>( 280 fn intern_substitution<E>(
274 &self, 281 &self,
275 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, 282 data: impl IntoIterator<Item = Result<GenericArg, E>>,
276 ) -> Result<Self::InternedSubstitution, E> { 283 ) -> Result<Self::InternedSubstitution, E> {
277 data.into_iter().collect() 284 Ok(Interned::new(InternedSubstitutionInner(data.into_iter().collect::<Result<SmallVec<_>, _>>()?)))
278 } 285 }
279 286
280 fn substitution_data<'a>( 287 fn substitution_data<'a>(
281 &self, 288 &self,
282 substitution: &'a Self::InternedSubstitution, 289 substitution: &'a Self::InternedSubstitution,
283 ) -> &'a [GenericArg<Self>] { 290 ) -> &'a [GenericArg] {
284 substitution 291 &substitution.as_ref().0
285 } 292 }
286 293
287 fn intern_program_clause( 294 fn intern_program_clause(
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 7818f6387..e78581ea5 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -99,7 +99,7 @@ pub(super) fn generic_predicate_to_inline_bound(
99 // have the expected self type 99 // have the expected self type
100 return None; 100 return None;
101 } 101 }
102 let args_no_self = trait_ref.substitution.interned()[1..] 102 let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
103 .iter() 103 .iter()
104 .map(|ty| ty.clone().cast(&Interner)) 104 .map(|ty| ty.clone().cast(&Interner))
105 .collect(); 105 .collect();
@@ -111,7 +111,7 @@ pub(super) fn generic_predicate_to_inline_bound(
111 return None; 111 return None;
112 } 112 }
113 let trait_ = projection_ty.trait_(db); 113 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..]
115 .iter() 115 .iter()
116 .map(|ty| ty.clone().cast(&Interner)) 116 .map(|ty| ty.clone().cast(&Interner))
117 .collect(); 117 .collect();