Skip to content

Commit 2a949d8

Browse files
Store some hir_def Paths in the type ref source maps
Most paths are types and therefore already are in the source map, but the trait in impl trait and in bounds are not. We do this by storing them basically as `TypeRef`s. For convenience, I created a wrapper around `TypeRefId` called `PathId` that always stores a path, and implemented indexing from the types map to it. Fortunately, this change impacts memory usage negligibly (adds 2mb to `analysis-stats .`, but that could be just fluff). Probably because there aren't that many trait bounds and impl traits, and this also shrinks `TypeBound` by 8 bytes. I also added an accessor to `TypesSourceMap` to get the source code, which will be needed for diagnostics.
1 parent 609621d commit 2a949d8

File tree

18 files changed

+144
-77
lines changed

18 files changed

+144
-77
lines changed

src/tools/rust-analyzer/crates/hir-def/src/body.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
path::{ModPath, Path},
3232
src::HasSource,
3333
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
34-
BlockId, DefWithBodyId, HasModule, Lookup,
34+
BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
3535
};
3636

3737
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
@@ -160,9 +160,6 @@ pub struct BodySourceMap {
160160
diagnostics: Vec<BodyDiagnostic>,
161161
}
162162

163-
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
164-
pub struct SyntheticSyntax;
165-
166163
#[derive(Debug, Eq, PartialEq)]
167164
pub enum BodyDiagnostic {
168165
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },

src/tools/rust-analyzer/crates/hir-def/src/data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl ImplData {
369369

370370
let item_tree = tree_id.item_tree(db);
371371
let impl_def = &item_tree[tree_id.value];
372-
let target_trait = impl_def.target_trait.clone();
372+
let target_trait = impl_def.target_trait;
373373
let self_ty = impl_def.self_ty;
374374
let is_negative = impl_def.is_negative;
375375
let is_unsafe = impl_def.is_unsafe;

src/tools/rust-analyzer/crates/hir-def/src/generics.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use crate::{
2626
nameres::{DefMap, MacroSubNs},
2727
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
2828
type_ref::{
29-
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
30-
TypesSourceMap,
29+
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
30+
TypesMap, TypesSourceMap,
3131
},
3232
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
3333
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
@@ -874,14 +874,20 @@ fn copy_type_bound(
874874
to: &mut TypesMap,
875875
to_source_map: &mut TypesSourceMap,
876876
) -> TypeBound {
877+
let mut copy_path_id = |path: PathId| {
878+
let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
879+
let new_path_id = to.types.alloc(TypeRef::Path(new_path));
880+
if let Some(&ptr) = from_source_map.types_map_back.get(path.type_ref()) {
881+
to_source_map.types_map_back.insert(new_path_id, ptr);
882+
}
883+
PathId::from_type_ref_unchecked(new_path_id)
884+
};
885+
877886
match bound {
878-
TypeBound::Path(path, modifier) => {
879-
TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
887+
&TypeBound::Path(path, modifier) => TypeBound::Path(copy_path_id(path), modifier),
888+
TypeBound::ForLifetime(lifetimes, path) => {
889+
TypeBound::ForLifetime(lifetimes.clone(), copy_path_id(*path))
880890
}
881-
TypeBound::ForLifetime(lifetimes, path) => TypeBound::ForLifetime(
882-
lifetimes.clone(),
883-
copy_path(path, from, from_source_map, to, to_source_map),
884-
),
885891
TypeBound::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
886892
TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
887893
TypeBound::Error => TypeBound::Error,

src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323
hir::Literal,
2424
lower::LowerCtx,
2525
path::{GenericArg, Path},
26+
SyntheticSyntax,
2627
};
2728

2829
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -91,19 +92,37 @@ impl Rawness {
9192
}
9293
}
9394

94-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
95+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
96+
/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
97+
/// impl's trait, that are always paths but need to be traced back to source code.
98+
pub struct PathId(TypeRefId);
99+
100+
impl PathId {
101+
#[inline]
102+
pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
103+
Self(type_ref)
104+
}
105+
106+
#[inline]
107+
pub fn type_ref(self) -> TypeRefId {
108+
self.0
109+
}
110+
}
111+
112+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
95113
pub struct TraitRef {
96-
pub path: Path,
114+
pub path: PathId,
97115
}
98116

99117
impl TraitRef {
100118
/// Converts an `ast::PathType` to a `hir::TraitRef`.
101119
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
102120
// FIXME: Use `Path::from_src`
103-
match node {
104-
ast::Type::PathType(path) => {
105-
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
106-
}
121+
match &node {
122+
ast::Type::PathType(path) => path
123+
.path()
124+
.and_then(|it| ctx.lower_path(it))
125+
.map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
107126
_ => None,
108127
}
109128
}
@@ -173,11 +192,24 @@ impl TypesMap {
173192
impl Index<TypeRefId> for TypesMap {
174193
type Output = TypeRef;
175194

195+
#[inline]
176196
fn index(&self, index: TypeRefId) -> &Self::Output {
177197
&self.types[index]
178198
}
179199
}
180200

201+
impl Index<PathId> for TypesMap {
202+
type Output = Path;
203+
204+
#[inline]
205+
fn index(&self, index: PathId) -> &Self::Output {
206+
let TypeRef::Path(path) = &self[index.type_ref()] else {
207+
unreachable!("`PathId` always points to `TypeRef::Path`");
208+
};
209+
path
210+
}
211+
}
212+
181213
pub type TypePtr = AstPtr<ast::Type>;
182214
pub type TypeSource = InFile<TypePtr>;
183215

@@ -187,6 +219,10 @@ pub struct TypesSourceMap {
187219
}
188220

189221
impl TypesSourceMap {
222+
pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
223+
self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
224+
}
225+
190226
pub(crate) fn shrink_to_fit(&mut self) {
191227
let TypesSourceMap { types_map_back } = self;
192228
types_map_back.shrink_to_fit();
@@ -214,15 +250,15 @@ impl LifetimeRef {
214250

215251
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
216252
pub enum TypeBound {
217-
Path(Path, TraitBoundModifier),
218-
ForLifetime(Box<[Name]>, Path),
253+
Path(PathId, TraitBoundModifier),
254+
ForLifetime(Box<[Name]>, PathId),
219255
Lifetime(LifetimeRef),
220256
Use(Box<[UseArgRef]>),
221257
Error,
222258
}
223259

224260
#[cfg(target_pointer_width = "64")]
225-
const _: [(); 32] = [(); ::std::mem::size_of::<TypeBound>()];
261+
const _: [(); 24] = [(); ::std::mem::size_of::<TypeBound>()];
226262

227263
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
228264
pub enum UseArgRef {
@@ -365,8 +401,8 @@ impl TypeRef {
365401
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
366402
for bound in bounds {
367403
match bound {
368-
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
369-
go_path(path, f, map)
404+
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
405+
go_path(&map[path], f, map)
370406
}
371407
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
372408
}
@@ -397,8 +433,8 @@ impl TypeRef {
397433
}
398434
for bound in binding.bounds.iter() {
399435
match bound {
400-
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
401-
go_path(path, f, map)
436+
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
437+
go_path(&map[path], f, map)
402438
}
403439
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
404440
}
@@ -425,16 +461,18 @@ pub(crate) fn type_bounds_from_ast(
425461

426462
impl TypeBound {
427463
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
428-
let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
464+
let mut lower_path_type = |path_type: &ast::PathType| ctx.lower_path(path_type.path()?);
429465

430466
match node.kind() {
431467
ast::TypeBoundKind::PathType(path_type) => {
432468
let m = match node.question_mark_token() {
433469
Some(_) => TraitBoundModifier::Maybe,
434470
None => TraitBoundModifier::None,
435471
};
436-
lower_path_type(path_type)
437-
.map(|p| TypeBound::Path(p, m))
472+
lower_path_type(&path_type)
473+
.map(|p| {
474+
TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
475+
})
438476
.unwrap_or(TypeBound::Error)
439477
}
440478
ast::TypeBoundKind::ForType(for_type) => {
@@ -445,12 +483,14 @@ impl TypeBound {
445483
.collect(),
446484
None => Box::default(),
447485
};
448-
let path = for_type.ty().and_then(|ty| match ty {
449-
ast::Type::PathType(path_type) => lower_path_type(path_type),
486+
let path = for_type.ty().and_then(|ty| match &ty {
487+
ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
450488
_ => None,
451489
});
452490
match path {
453-
Some(p) => TypeBound::ForLifetime(lt_refs, p),
491+
Some((p, ty)) => {
492+
TypeBound::ForLifetime(lt_refs, ctx.alloc_path(p, AstPtr::new(&ty)))
493+
}
454494
None => TypeBound::Error,
455495
}
456496
}
@@ -470,10 +510,10 @@ impl TypeBound {
470510
}
471511
}
472512

473-
pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
513+
pub fn as_path<'a>(&self, map: &'a TypesMap) -> Option<(&'a Path, TraitBoundModifier)> {
474514
match self {
475-
TypeBound::Path(p, m) => Some((p, m)),
476-
TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
515+
&TypeBound::Path(p, m) => Some((&map[p], m)),
516+
&TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
477517
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
478518
}
479519
}

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::{
3434
lower::LowerCtx,
3535
path::AssociatedTypeBinding,
3636
type_ref::{
37-
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
37+
LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
3838
TypesMap, TypesSourceMap,
3939
},
4040
visibility::RawVisibility,
@@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
514514
};
515515

516516
let ret_type = if func.async_token().is_some() {
517-
let future_impl = desugar_future_path(ret_type);
517+
let future_impl = desugar_future_path(&mut body_ctx, ret_type);
518518
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
519519
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
520520
} else {
@@ -936,7 +936,7 @@ impl<'a> Ctx<'a> {
936936
}
937937
}
938938

939-
fn desugar_future_path(orig: TypeRefId) -> Path {
939+
fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId {
940940
let path = path![core::future::Future];
941941
let mut generic_args: Vec<_> =
942942
std::iter::repeat(None).take(path.segments().len() - 1).collect();
@@ -948,7 +948,8 @@ fn desugar_future_path(orig: TypeRefId) -> Path {
948948
};
949949
generic_args.push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));
950950

951-
Path::from_known_path(path, generic_args)
951+
let path = Path::from_known_path(path, generic_args);
952+
PathId::from_type_ref_unchecked(ctx.alloc_type_ref_desugared(TypeRef::Path(path)))
952953
}
953954

954955
enum HasImplicitSelf {

src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ impl Printer<'_> {
484484
w!(self, "!");
485485
}
486486
if let Some(tr) = target_trait {
487-
self.print_path(&tr.path, types_map);
487+
self.print_path(&types_map[tr.path], types_map);
488488
w!(self, " for ");
489489
}
490490
self.print_type_ref(*self_ty, types_map);

src/tools/rust-analyzer/crates/hir-def/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
15351535
pub struct UnresolvedMacro {
15361536
pub path: hir_expand::mod_path::ModPath,
15371537
}
1538+
1539+
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
1540+
pub struct SyntheticSyntax;

src/tools/rust-analyzer/crates/hir-def/src/lower.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use triomphe::Arc;
1010
use crate::{
1111
db::DefDatabase,
1212
path::Path,
13-
type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
13+
type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
1414
};
1515

1616
pub struct LowerCtx<'a> {
@@ -142,4 +142,8 @@ impl<'a> LowerCtx<'a> {
142142
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
143143
self.types_map.types.alloc(TypeRef::Error)
144144
}
145+
146+
pub(crate) fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
147+
PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
148+
}
145149
}

src/tools/rust-analyzer/crates/hir-def/src/pretty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,15 @@ pub(crate) fn print_type_bounds(
271271
TraitBoundModifier::None => (),
272272
TraitBoundModifier::Maybe => write!(buf, "?")?,
273273
}
274-
print_path(db, path, map, buf, edition)?;
274+
print_path(db, &map[*path], map, buf, edition)?;
275275
}
276276
TypeBound::ForLifetime(lifetimes, path) => {
277277
write!(
278278
buf,
279279
"for<{}> ",
280280
lifetimes.iter().map(|it| it.display(db.upcast(), edition)).format(", ")
281281
)?;
282-
print_path(db, path, map, buf, edition)?;
282+
print_path(db, &map[*path], map, buf, edition)?;
283283
}
284284
TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition))?,
285285
TypeBound::Use(args) => {

src/tools/rust-analyzer/crates/hir-def/src/resolver.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,10 +576,12 @@ impl Resolver {
576576
match scope {
577577
Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
578578
&Scope::ImplDefScope(impl_) => {
579-
if let Some(target_trait) = &db.impl_data(impl_).target_trait {
580-
if let Some(TypeNs::TraitId(trait_)) =
581-
self.resolve_path_in_type_ns_fully(db, &target_trait.path)
582-
{
579+
let impl_data = db.impl_data(impl_);
580+
if let Some(target_trait) = impl_data.target_trait {
581+
if let Some(TypeNs::TraitId(trait_)) = self.resolve_path_in_type_ns_fully(
582+
db,
583+
&impl_data.types_map[target_trait.path],
584+
) {
583585
traits.insert(trait_);
584586
}
585587
}

0 commit comments

Comments
 (0)