about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2024-11-19 19:57:07 +0200
committerChayim Refael Friedman <chayimfr@gmail.com>2024-12-04 14:09:50 +0200
commit2a949d8725a1027ffe8ef49c1303bc95d6192ce8 (patch)
tree221b2bfbd5aa16ee5c04f60ab012d37de16dc9a8
parent609621db7fc830d4cc81fa9aeb4aca297f9fb158 (diff)
downloadrust-2a949d8725a1027ffe8ef49c1303bc95d6192ce8.tar.gz
rust-2a949d8725a1027ffe8ef49c1303bc95d6192ce8.zip
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.
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs84
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lower.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/pretty.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs33
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs3
18 files changed, 144 insertions, 77 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index d4a1120908f..908f2050b5f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -31,7 +31,7 @@ use crate::{
     path::{ModPath, Path},
     src::HasSource,
     type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
-    BlockId, DefWithBodyId, HasModule, Lookup,
+    BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
 };
 
 /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
@@ -160,9 +160,6 @@ pub struct BodySourceMap {
     diagnostics: Vec<BodyDiagnostic>,
 }
 
-#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
-pub struct SyntheticSyntax;
-
 #[derive(Debug, Eq, PartialEq)]
 pub enum BodyDiagnostic {
     InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 2a13f74aac7..15dd6aba311 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -369,7 +369,7 @@ impl ImplData {
 
         let item_tree = tree_id.item_tree(db);
         let impl_def = &item_tree[tree_id.value];
-        let target_trait = impl_def.target_trait.clone();
+        let target_trait = impl_def.target_trait;
         let self_ty = impl_def.self_ty;
         let is_negative = impl_def.is_negative;
         let is_unsafe = impl_def.is_unsafe;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index 11e9bb0d886..fdcb10e9988 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -26,8 +26,8 @@ use crate::{
     nameres::{DefMap, MacroSubNs},
     path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
     type_ref::{
-        ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
-        TypesSourceMap,
+        ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
+        TypesMap, TypesSourceMap,
     },
     AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
     LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
@@ -874,14 +874,20 @@ fn copy_type_bound(
     to: &mut TypesMap,
     to_source_map: &mut TypesSourceMap,
 ) -> TypeBound {
+    let mut copy_path_id = |path: PathId| {
+        let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
+        let new_path_id = to.types.alloc(TypeRef::Path(new_path));
+        if let Some(&ptr) = from_source_map.types_map_back.get(path.type_ref()) {
+            to_source_map.types_map_back.insert(new_path_id, ptr);
+        }
+        PathId::from_type_ref_unchecked(new_path_id)
+    };
+
     match bound {
-        TypeBound::Path(path, modifier) => {
-            TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
+        &TypeBound::Path(path, modifier) => TypeBound::Path(copy_path_id(path), modifier),
+        TypeBound::ForLifetime(lifetimes, path) => {
+            TypeBound::ForLifetime(lifetimes.clone(), copy_path_id(*path))
         }
-        TypeBound::ForLifetime(lifetimes, path) => TypeBound::ForLifetime(
-            lifetimes.clone(),
-            copy_path(path, from, from_source_map, to, to_source_map),
-        ),
         TypeBound::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
         TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
         TypeBound::Error => TypeBound::Error,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 4d83ef99c84..15980ddccaf 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -23,6 +23,7 @@ use crate::{
     hir::Literal,
     lower::LowerCtx,
     path::{GenericArg, Path},
+    SyntheticSyntax,
 };
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -91,19 +92,37 @@ impl Rawness {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
+/// impl's trait, that are always paths but need to be traced back to source code.
+pub struct PathId(TypeRefId);
+
+impl PathId {
+    #[inline]
+    pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
+        Self(type_ref)
+    }
+
+    #[inline]
+    pub fn type_ref(self) -> TypeRefId {
+        self.0
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct TraitRef {
-    pub path: Path,
+    pub path: PathId,
 }
 
 impl TraitRef {
     /// Converts an `ast::PathType` to a `hir::TraitRef`.
     pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
         // FIXME: Use `Path::from_src`
-        match node {
-            ast::Type::PathType(path) => {
-                path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
-            }
+        match &node {
+            ast::Type::PathType(path) => path
+                .path()
+                .and_then(|it| ctx.lower_path(it))
+                .map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
             _ => None,
         }
     }
@@ -173,11 +192,24 @@ impl TypesMap {
 impl Index<TypeRefId> for TypesMap {
     type Output = TypeRef;
 
+    #[inline]
     fn index(&self, index: TypeRefId) -> &Self::Output {
         &self.types[index]
     }
 }
 
+impl Index<PathId> for TypesMap {
+    type Output = Path;
+
+    #[inline]
+    fn index(&self, index: PathId) -> &Self::Output {
+        let TypeRef::Path(path) = &self[index.type_ref()] else {
+            unreachable!("`PathId` always points to `TypeRef::Path`");
+        };
+        path
+    }
+}
+
 pub type TypePtr = AstPtr<ast::Type>;
 pub type TypeSource = InFile<TypePtr>;
 
@@ -187,6 +219,10 @@ pub struct TypesSourceMap {
 }
 
 impl TypesSourceMap {
+    pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
+        self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
+    }
+
     pub(crate) fn shrink_to_fit(&mut self) {
         let TypesSourceMap { types_map_back } = self;
         types_map_back.shrink_to_fit();
@@ -214,15 +250,15 @@ impl LifetimeRef {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum TypeBound {
-    Path(Path, TraitBoundModifier),
-    ForLifetime(Box<[Name]>, Path),
+    Path(PathId, TraitBoundModifier),
+    ForLifetime(Box<[Name]>, PathId),
     Lifetime(LifetimeRef),
     Use(Box<[UseArgRef]>),
     Error,
 }
 
 #[cfg(target_pointer_width = "64")]
-const _: [(); 32] = [(); ::std::mem::size_of::<TypeBound>()];
+const _: [(); 24] = [(); ::std::mem::size_of::<TypeBound>()];
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum UseArgRef {
@@ -365,8 +401,8 @@ impl TypeRef {
                 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
                     for bound in bounds {
                         match bound {
-                            TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
-                                go_path(path, f, map)
+                            &TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
+                                go_path(&map[path], f, map)
                             }
                             TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
                         }
@@ -397,8 +433,8 @@ impl TypeRef {
                         }
                         for bound in binding.bounds.iter() {
                             match bound {
-                                TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
-                                    go_path(path, f, map)
+                                &TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
+                                    go_path(&map[path], f, map)
                                 }
                                 TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
                             }
@@ -425,7 +461,7 @@ pub(crate) fn type_bounds_from_ast(
 
 impl TypeBound {
     pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
-        let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
+        let mut lower_path_type = |path_type: &ast::PathType| ctx.lower_path(path_type.path()?);
 
         match node.kind() {
             ast::TypeBoundKind::PathType(path_type) => {
@@ -433,8 +469,10 @@ impl TypeBound {
                     Some(_) => TraitBoundModifier::Maybe,
                     None => TraitBoundModifier::None,
                 };
-                lower_path_type(path_type)
-                    .map(|p| TypeBound::Path(p, m))
+                lower_path_type(&path_type)
+                    .map(|p| {
+                        TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
+                    })
                     .unwrap_or(TypeBound::Error)
             }
             ast::TypeBoundKind::ForType(for_type) => {
@@ -445,12 +483,14 @@ impl TypeBound {
                         .collect(),
                     None => Box::default(),
                 };
-                let path = for_type.ty().and_then(|ty| match ty {
-                    ast::Type::PathType(path_type) => lower_path_type(path_type),
+                let path = for_type.ty().and_then(|ty| match &ty {
+                    ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
                     _ => None,
                 });
                 match path {
-                    Some(p) => TypeBound::ForLifetime(lt_refs, p),
+                    Some((p, ty)) => {
+                        TypeBound::ForLifetime(lt_refs, ctx.alloc_path(p, AstPtr::new(&ty)))
+                    }
                     None => TypeBound::Error,
                 }
             }
@@ -470,10 +510,10 @@ impl TypeBound {
         }
     }
 
-    pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
+    pub fn as_path<'a>(&self, map: &'a TypesMap) -> Option<(&'a Path, TraitBoundModifier)> {
         match self {
-            TypeBound::Path(p, m) => Some((p, m)),
-            TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
+            &TypeBound::Path(p, m) => Some((&map[p], m)),
+            &TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
             TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index d519c1708b3..71848845a84 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -34,7 +34,7 @@ use crate::{
     lower::LowerCtx,
     path::AssociatedTypeBinding,
     type_ref::{
-        LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
+        LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
         TypesMap, TypesSourceMap,
     },
     visibility::RawVisibility,
@@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
         };
 
         let ret_type = if func.async_token().is_some() {
-            let future_impl = desugar_future_path(ret_type);
+            let future_impl = desugar_future_path(&mut body_ctx, ret_type);
             let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
             body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
         } else {
@@ -936,7 +936,7 @@ impl<'a> Ctx<'a> {
     }
 }
 
-fn desugar_future_path(orig: TypeRefId) -> Path {
+fn desugar_future_path(ctx: &mut LowerCtx<'_>, orig: TypeRefId) -> PathId {
     let path = path![core::future::Future];
     let mut generic_args: Vec<_> =
         std::iter::repeat(None).take(path.segments().len() - 1).collect();
@@ -948,7 +948,8 @@ fn desugar_future_path(orig: TypeRefId) -> Path {
     };
     generic_args.push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));
 
-    Path::from_known_path(path, generic_args)
+    let path = Path::from_known_path(path, generic_args);
+    PathId::from_type_ref_unchecked(ctx.alloc_type_ref_desugared(TypeRef::Path(path)))
 }
 
 enum HasImplicitSelf {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index b6816a1f968..0c5e3a3620a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -484,7 +484,7 @@ impl Printer<'_> {
                     w!(self, "!");
                 }
                 if let Some(tr) = target_trait {
-                    self.print_path(&tr.path, types_map);
+                    self.print_path(&types_map[tr.path], types_map);
                     w!(self, " for ");
                 }
                 self.print_type_ref(*self_ty, types_map);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index eb55ba1d53d..8af27513ebc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
 pub struct UnresolvedMacro {
     pub path: hir_expand::mod_path::ModPath,
 }
+
+#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
+pub struct SyntheticSyntax;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
index 350bb8d5172..7cddd48eb17 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
@@ -10,7 +10,7 @@ use triomphe::Arc;
 use crate::{
     db::DefDatabase,
     path::Path,
-    type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
+    type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
 };
 
 pub struct LowerCtx<'a> {
@@ -142,4 +142,8 @@ impl<'a> LowerCtx<'a> {
     pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
         self.types_map.types.alloc(TypeRef::Error)
     }
+
+    pub(crate) fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
+        PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
index 9ceb82d5fd6..eb9488feaa9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
@@ -271,7 +271,7 @@ pub(crate) fn print_type_bounds(
                     TraitBoundModifier::None => (),
                     TraitBoundModifier::Maybe => write!(buf, "?")?,
                 }
-                print_path(db, path, map, buf, edition)?;
+                print_path(db, &map[*path], map, buf, edition)?;
             }
             TypeBound::ForLifetime(lifetimes, path) => {
                 write!(
@@ -279,7 +279,7 @@ pub(crate) fn print_type_bounds(
                     "for<{}> ",
                     lifetimes.iter().map(|it| it.display(db.upcast(), edition)).format(", ")
                 )?;
-                print_path(db, path, map, buf, edition)?;
+                print_path(db, &map[*path], map, buf, edition)?;
             }
             TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition))?,
             TypeBound::Use(args) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 26655e40ca7..0ca7070fd05 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -576,10 +576,12 @@ impl Resolver {
             match scope {
                 Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
                 &Scope::ImplDefScope(impl_) => {
-                    if let Some(target_trait) = &db.impl_data(impl_).target_trait {
-                        if let Some(TypeNs::TraitId(trait_)) =
-                            self.resolve_path_in_type_ns_fully(db, &target_trait.path)
-                        {
+                    let impl_data = db.impl_data(impl_);
+                    if let Some(target_trait) = impl_data.target_trait {
+                        if let Some(TypeNs::TraitId(trait_)) = self.resolve_path_in_type_ns_fully(
+                            db,
+                            &impl_data.types_map[target_trait.path],
+                        ) {
                             traits.insert(trait_);
                         }
                     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 4e95bdf219f..94a340fbec2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -2062,12 +2062,12 @@ impl HirDisplayWithTypesMap for TypeBound {
         types_map: &TypesMap,
     ) -> Result<(), HirDisplayError> {
         match self {
-            TypeBound::Path(path, modifier) => {
+            &TypeBound::Path(path, modifier) => {
                 match modifier {
                     TraitBoundModifier::None => (),
                     TraitBoundModifier::Maybe => write!(f, "?")?,
                 }
-                path.hir_fmt(f, types_map)
+                types_map[path].hir_fmt(f, types_map)
             }
             TypeBound::Lifetime(lifetime) => {
                 write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
@@ -2079,7 +2079,7 @@ impl HirDisplayWithTypesMap for TypeBound {
                     "for<{}> ",
                     lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
                 )?;
-                path.hir_fmt(f, types_map)
+                types_map[*path].hir_fmt(f, types_map)
             }
             TypeBound::Use(args) => {
                 let edition = f.edition();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index b868ea95f85..fc0af0cec90 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -33,8 +33,8 @@ use hir_def::{
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
     resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
     type_ref::{
-        ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
-        TypeRefId, TypesMap, TypesSourceMap,
+        ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
+        TypeRef, TypeRefId, TypesMap, TypesSourceMap,
     },
     AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
     FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId,
@@ -264,7 +264,8 @@ impl<'a> TyLoweringContext<'a> {
                     .intern(Interner)
             }
             TypeRef::Path(path) => {
-                let (ty, res_) = self.lower_path(path);
+                let (ty, res_) =
+                    self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
                 res = res_;
                 ty
             }
@@ -677,7 +678,7 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
     }
 
-    pub(crate) fn lower_path(&mut self, path: &Path) -> (Ty, Option<TypeNs>) {
+    pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option<TypeNs>) {
         // Resolve the path (in type namespace)
         if let Some(type_ref) = path.type_anchor() {
             let (ty, res) = self.lower_ty_ext(type_ref);
@@ -692,7 +693,7 @@ impl<'a> TyLoweringContext<'a> {
 
         if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
             // trait object type without dyn
-            let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
+            let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
             let ty = self.lower_dyn_trait(&[bound]);
             return (ty, None);
         }
@@ -998,7 +999,12 @@ impl<'a> TyLoweringContext<'a> {
         TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
     }
 
-    fn lower_trait_ref_from_path(&mut self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> {
+    fn lower_trait_ref_from_path(
+        &mut self,
+        path_id: PathId,
+        explicit_self_ty: Ty,
+    ) -> Option<TraitRef> {
+        let path = &self.types_map[path_id];
         let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? {
             // FIXME(trait_alias): We need to handle trait alias here.
             TypeNs::TraitId(tr) => tr,
@@ -1013,7 +1019,7 @@ impl<'a> TyLoweringContext<'a> {
         trait_ref: &HirTraitRef,
         explicit_self_ty: Ty,
     ) -> Option<TraitRef> {
-        self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
+        self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty)
     }
 
     fn trait_ref_substs_from_path(
@@ -1072,11 +1078,11 @@ impl<'a> TyLoweringContext<'a> {
     ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let mut trait_ref = None;
         let clause = match bound {
-            TypeBound::Path(path, TraitBoundModifier::None) => {
+            &TypeBound::Path(path, TraitBoundModifier::None) => {
                 trait_ref = self.lower_trait_ref_from_path(path, self_ty);
                 trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
             }
-            TypeBound::Path(path, TraitBoundModifier::Maybe) => {
+            &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
                 let sized_trait = self
                     .db
                     .lang_item(self.resolver.krate(), LangItem::Sized)
@@ -1092,7 +1098,7 @@ impl<'a> TyLoweringContext<'a> {
                 }
                 None
             }
-            TypeBound::ForLifetime(_, path) => {
+            &TypeBound::ForLifetime(_, path) => {
                 // FIXME Don't silently drop the hrtb lifetimes here
                 trait_ref = self.lower_trait_ref_from_path(path, self_ty);
                 trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
@@ -1121,8 +1127,8 @@ impl<'a> TyLoweringContext<'a> {
         trait_ref: TraitRef,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let last_segment = match bound {
-            TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
-                path.segments().last()
+            &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
+                self.types_map[path].segments().last()
             }
             TypeBound::Path(_, TraitBoundModifier::Maybe)
             | TypeBound::Use(_)
@@ -1593,9 +1599,10 @@ pub(crate) fn generic_predicates_for_param_query(
             }
 
             match bound {
-                TypeBound::ForLifetime(_, path) | TypeBound::Path(path, _) => {
+                &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
                     // Only lower the bound if the trait could possibly define the associated
                     // type we're looking for.
+                    let path = &ctx.types_map[path];
 
                     let Some(assoc_name) = &assoc_name else { return true };
                     let Some(TypeNs::TraitId(tr)) =
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index bcf9d5ceff0..cabeeea2bd8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -18,13 +18,13 @@ use std::sync::LazyLock;
 use base_db::SourceDatabaseFileInputExt as _;
 use expect_test::Expect;
 use hir_def::{
-    body::{Body, BodySourceMap, SyntheticSyntax},
+    body::{Body, BodySourceMap},
     db::DefDatabase,
     hir::{ExprId, Pat, PatId},
     item_scope::ItemScope,
     nameres::DefMap,
     src::HasSource,
-    AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
+    AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax,
 };
 use hir_expand::{db::ExpandDatabase, FileRange, InFile};
 use itertools::Itertools;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 28bda1e10e5..06719b09f73 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -185,7 +185,7 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
                     }
                 };
                 match is_trait {
-                    true => bound.as_path(),
+                    true => bound.as_path(&generic_params.types_map),
                     false => None,
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 9ca021027d5..9df6ca58f56 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -13,7 +13,7 @@ use hir_ty::{
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 pub use hir_def::VariantId;
-use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
+use hir_def::{hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId, SyntheticSyntax};
 use hir_expand::{name::Name, HirFileId, InFile};
 use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
 use triomphe::Arc;
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 9275f45d881..959d62d5951 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -132,12 +132,18 @@ impl HirDisplay for Function {
         } else {
             match &data.types_map[data.ret_type] {
                 TypeRef::ImplTrait(bounds) => match &bounds[0] {
-                    TypeBound::Path(path, _) => Some(
-                        *path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
-                            [0]
-                        .type_ref
-                        .as_ref()
-                        .unwrap(),
+                    &TypeBound::Path(path, _) => Some(
+                        *data.types_map[path]
+                            .segments()
+                            .iter()
+                            .last()
+                            .unwrap()
+                            .args_and_bindings
+                            .unwrap()
+                            .bindings[0]
+                            .type_ref
+                            .as_ref()
+                            .unwrap(),
                     ),
                     _ => None,
                 },
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 0b2ba56b1ff..dc1d1efe60c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -43,7 +43,7 @@ use arrayvec::ArrayVec;
 use base_db::{CrateDisplayName, CrateId, CrateOrigin};
 use either::Either;
 use hir_def::{
-    body::{BodyDiagnostic, SyntheticSyntax},
+    body::BodyDiagnostic,
     data::adt::VariantData,
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
@@ -57,8 +57,8 @@ use hir_def::{
     AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
     DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
     HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
-    MacroExpander, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId,
-    TypeOrConstParamId, TypeParamId, UnionId,
+    MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId,
+    TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
 };
 use hir_expand::{
     attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 802d0c69a47..e3ea441f3ab 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -13,8 +13,9 @@ use hir::{
     ModuleDef, Name,
 };
 use hir_def::{
-    body::{BodySourceMap, SyntheticSyntax},
+    body::BodySourceMap,
     hir::{ExprId, PatId},
+    SyntheticSyntax,
 };
 use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
 use ide::{