mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
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.
This commit is contained in:
parent
26bc01dae3
commit
4e475a3245
18 changed files with 145 additions and 78 deletions
|
@ -31,7 +31,7 @@ use crate::{
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
|
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.
|
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
|
||||||
|
@ -160,9 +160,6 @@ pub struct BodySourceMap {
|
||||||
diagnostics: Vec<BodyDiagnostic>,
|
diagnostics: Vec<BodyDiagnostic>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
|
|
||||||
pub struct SyntheticSyntax;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum BodyDiagnostic {
|
pub enum BodyDiagnostic {
|
||||||
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
|
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
|
||||||
|
|
|
@ -369,7 +369,7 @@ impl ImplData {
|
||||||
|
|
||||||
let item_tree = tree_id.item_tree(db);
|
let item_tree = tree_id.item_tree(db);
|
||||||
let impl_def = &item_tree[tree_id.value];
|
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 self_ty = impl_def.self_ty;
|
||||||
let is_negative = impl_def.is_negative;
|
let is_negative = impl_def.is_negative;
|
||||||
let is_unsafe = impl_def.is_unsafe;
|
let is_unsafe = impl_def.is_unsafe;
|
||||||
|
|
|
@ -26,8 +26,8 @@ use crate::{
|
||||||
nameres::{DefMap, MacroSubNs},
|
nameres::{DefMap, MacroSubNs},
|
||||||
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
|
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
|
||||||
type_ref::{
|
type_ref::{
|
||||||
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
|
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
|
||||||
TypesSourceMap,
|
TypesMap, TypesSourceMap,
|
||||||
},
|
},
|
||||||
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
|
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
|
||||||
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
||||||
|
@ -874,14 +874,20 @@ fn copy_type_bound(
|
||||||
to: &mut TypesMap,
|
to: &mut TypesMap,
|
||||||
to_source_map: &mut TypesSourceMap,
|
to_source_map: &mut TypesSourceMap,
|
||||||
) -> TypeBound {
|
) -> TypeBound {
|
||||||
match bound {
|
let mut copy_path_id = |path: PathId| {
|
||||||
TypeBound::Path(path, modifier) => {
|
let new_path = copy_path(&from[path], from, from_source_map, to, to_source_map);
|
||||||
TypeBound::Path(copy_path(path, from, from_source_map, to, to_source_map), *modifier)
|
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_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::Lifetime(lifetime) => TypeBound::Lifetime(lifetime.clone()),
|
||||||
TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
|
TypeBound::Use(use_args) => TypeBound::Use(use_args.clone()),
|
||||||
TypeBound::Error => TypeBound::Error,
|
TypeBound::Error => TypeBound::Error,
|
||||||
|
|
|
@ -23,6 +23,7 @@ use crate::{
|
||||||
hir::Literal,
|
hir::Literal,
|
||||||
lower::LowerCtx,
|
lower::LowerCtx,
|
||||||
path::{GenericArg, Path},
|
path::{GenericArg, Path},
|
||||||
|
SyntheticSyntax,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[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 struct TraitRef {
|
||||||
pub path: Path,
|
pub path: PathId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitRef {
|
impl TraitRef {
|
||||||
/// Converts an `ast::PathType` to a `hir::TraitRef`.
|
/// Converts an `ast::PathType` to a `hir::TraitRef`.
|
||||||
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
|
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
|
||||||
// FIXME: Use `Path::from_src`
|
// FIXME: Use `Path::from_src`
|
||||||
match node {
|
match &node {
|
||||||
ast::Type::PathType(path) => {
|
ast::Type::PathType(path) => path
|
||||||
path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
|
.path()
|
||||||
}
|
.and_then(|it| ctx.lower_path(it))
|
||||||
|
.map(|path| TraitRef { path: ctx.alloc_path(path, AstPtr::new(&node)) }),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,11 +192,24 @@ impl TypesMap {
|
||||||
impl Index<TypeRefId> for TypesMap {
|
impl Index<TypeRefId> for TypesMap {
|
||||||
type Output = TypeRef;
|
type Output = TypeRef;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn index(&self, index: TypeRefId) -> &Self::Output {
|
fn index(&self, index: TypeRefId) -> &Self::Output {
|
||||||
&self.types[index]
|
&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 TypePtr = AstPtr<ast::Type>;
|
||||||
pub type TypeSource = InFile<TypePtr>;
|
pub type TypeSource = InFile<TypePtr>;
|
||||||
|
|
||||||
|
@ -187,6 +219,10 @@ pub struct TypesSourceMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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) {
|
pub(crate) fn shrink_to_fit(&mut self) {
|
||||||
let TypesSourceMap { types_map_back } = self;
|
let TypesSourceMap { types_map_back } = self;
|
||||||
types_map_back.shrink_to_fit();
|
types_map_back.shrink_to_fit();
|
||||||
|
@ -214,15 +250,15 @@ impl LifetimeRef {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum TypeBound {
|
pub enum TypeBound {
|
||||||
Path(Path, TraitBoundModifier),
|
Path(PathId, TraitBoundModifier),
|
||||||
ForLifetime(Box<[Name]>, Path),
|
ForLifetime(Box<[Name]>, PathId),
|
||||||
Lifetime(LifetimeRef),
|
Lifetime(LifetimeRef),
|
||||||
Use(Box<[UseArgRef]>),
|
Use(Box<[UseArgRef]>),
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[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)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum UseArgRef {
|
pub enum UseArgRef {
|
||||||
|
@ -365,8 +401,8 @@ impl TypeRef {
|
||||||
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
|
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
|
||||||
for bound in bounds {
|
for bound in bounds {
|
||||||
match bound {
|
match bound {
|
||||||
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
|
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
|
||||||
go_path(path, f, map)
|
go_path(&map[path], f, map)
|
||||||
}
|
}
|
||||||
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
|
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
|
||||||
}
|
}
|
||||||
|
@ -397,8 +433,8 @@ impl TypeRef {
|
||||||
}
|
}
|
||||||
for bound in binding.bounds.iter() {
|
for bound in binding.bounds.iter() {
|
||||||
match bound {
|
match bound {
|
||||||
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
|
&TypeBound::Path(path, _) | &TypeBound::ForLifetime(_, path) => {
|
||||||
go_path(path, f, map)
|
go_path(&map[path], f, map)
|
||||||
}
|
}
|
||||||
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
|
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => (),
|
||||||
}
|
}
|
||||||
|
@ -425,7 +461,7 @@ pub(crate) fn type_bounds_from_ast(
|
||||||
|
|
||||||
impl TypeBound {
|
impl TypeBound {
|
||||||
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
|
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() {
|
match node.kind() {
|
||||||
ast::TypeBoundKind::PathType(path_type) => {
|
ast::TypeBoundKind::PathType(path_type) => {
|
||||||
|
@ -433,8 +469,10 @@ impl TypeBound {
|
||||||
Some(_) => TraitBoundModifier::Maybe,
|
Some(_) => TraitBoundModifier::Maybe,
|
||||||
None => TraitBoundModifier::None,
|
None => TraitBoundModifier::None,
|
||||||
};
|
};
|
||||||
lower_path_type(path_type)
|
lower_path_type(&path_type)
|
||||||
.map(|p| TypeBound::Path(p, m))
|
.map(|p| {
|
||||||
|
TypeBound::Path(ctx.alloc_path(p, AstPtr::new(&path_type).upcast()), m)
|
||||||
|
})
|
||||||
.unwrap_or(TypeBound::Error)
|
.unwrap_or(TypeBound::Error)
|
||||||
}
|
}
|
||||||
ast::TypeBoundKind::ForType(for_type) => {
|
ast::TypeBoundKind::ForType(for_type) => {
|
||||||
|
@ -445,12 +483,14 @@ impl TypeBound {
|
||||||
.collect(),
|
.collect(),
|
||||||
None => Box::default(),
|
None => Box::default(),
|
||||||
};
|
};
|
||||||
let path = for_type.ty().and_then(|ty| match ty {
|
let path = for_type.ty().and_then(|ty| match &ty {
|
||||||
ast::Type::PathType(path_type) => lower_path_type(path_type),
|
ast::Type::PathType(path_type) => lower_path_type(path_type).map(|p| (p, ty)),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
match path {
|
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,
|
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 {
|
match self {
|
||||||
TypeBound::Path(p, m) => Some((p, m)),
|
&TypeBound::Path(p, m) => Some((&map[p], m)),
|
||||||
TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
|
&TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
|
||||||
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
|
TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::{
|
||||||
lower::LowerCtx,
|
lower::LowerCtx,
|
||||||
path::AssociatedTypeBinding,
|
path::AssociatedTypeBinding,
|
||||||
type_ref::{
|
type_ref::{
|
||||||
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
|
LifetimeRef, PathId, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
|
||||||
TypesMap, TypesSourceMap,
|
TypesMap, TypesSourceMap,
|
||||||
},
|
},
|
||||||
visibility::RawVisibility,
|
visibility::RawVisibility,
|
||||||
|
@ -514,7 +514,7 @@ impl<'a> Ctx<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_type = if func.async_token().is_some() {
|
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);
|
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
|
||||||
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
|
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
|
||||||
} else {
|
} 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 path = path![core::future::Future];
|
||||||
let mut generic_args: Vec<_> =
|
let mut generic_args: Vec<_> =
|
||||||
std::iter::repeat(None).take(path.segments().len() - 1).collect();
|
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() }));
|
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 {
|
enum HasImplicitSelf {
|
||||||
|
|
|
@ -484,7 +484,7 @@ impl Printer<'_> {
|
||||||
w!(self, "!");
|
w!(self, "!");
|
||||||
}
|
}
|
||||||
if let Some(tr) = target_trait {
|
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 ");
|
w!(self, " for ");
|
||||||
}
|
}
|
||||||
self.print_type_ref(*self_ty, types_map);
|
self.print_type_ref(*self_ty, types_map);
|
||||||
|
|
|
@ -1535,3 +1535,6 @@ fn macro_call_as_call_id_with_eager(
|
||||||
pub struct UnresolvedMacro {
|
pub struct UnresolvedMacro {
|
||||||
pub path: hir_expand::mod_path::ModPath,
|
pub path: hir_expand::mod_path::ModPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
pub struct SyntheticSyntax;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use triomphe::Arc;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
path::Path,
|
path::Path,
|
||||||
type_ref::{TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
|
type_ref::{PathId, TypeBound, TypePtr, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct LowerCtx<'a> {
|
pub struct LowerCtx<'a> {
|
||||||
|
@ -142,4 +142,8 @@ impl<'a> LowerCtx<'a> {
|
||||||
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
|
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
|
||||||
self.types_map.types.alloc(TypeRef::Error)
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@ pub(crate) fn print_type_bounds(
|
||||||
TraitBoundModifier::None => (),
|
TraitBoundModifier::None => (),
|
||||||
TraitBoundModifier::Maybe => write!(buf, "?")?,
|
TraitBoundModifier::Maybe => write!(buf, "?")?,
|
||||||
}
|
}
|
||||||
print_path(db, path, map, buf, edition)?;
|
print_path(db, &map[*path], map, buf, edition)?;
|
||||||
}
|
}
|
||||||
TypeBound::ForLifetime(lifetimes, path) => {
|
TypeBound::ForLifetime(lifetimes, path) => {
|
||||||
write!(
|
write!(
|
||||||
|
@ -279,7 +279,7 @@ pub(crate) fn print_type_bounds(
|
||||||
"for<{}> ",
|
"for<{}> ",
|
||||||
lifetimes.iter().map(|it| it.display(db.upcast(), edition)).format(", ")
|
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::Lifetime(lt) => write!(buf, "{}", lt.name.display(db.upcast(), edition))?,
|
||||||
TypeBound::Use(args) => {
|
TypeBound::Use(args) => {
|
||||||
|
|
|
@ -576,10 +576,12 @@ impl Resolver {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
|
Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
|
||||||
&Scope::ImplDefScope(impl_) => {
|
&Scope::ImplDefScope(impl_) => {
|
||||||
if let Some(target_trait) = &db.impl_data(impl_).target_trait {
|
let impl_data = db.impl_data(impl_);
|
||||||
if let Some(TypeNs::TraitId(trait_)) =
|
if let Some(target_trait) = impl_data.target_trait {
|
||||||
self.resolve_path_in_type_ns_fully(db, &target_trait.path)
|
if let Some(TypeNs::TraitId(trait_)) = self.resolve_path_in_type_ns_fully(
|
||||||
{
|
db,
|
||||||
|
&impl_data.types_map[target_trait.path],
|
||||||
|
) {
|
||||||
traits.insert(trait_);
|
traits.insert(trait_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2062,12 +2062,12 @@ impl HirDisplayWithTypesMap for TypeBound {
|
||||||
types_map: &TypesMap,
|
types_map: &TypesMap,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
match self {
|
match self {
|
||||||
TypeBound::Path(path, modifier) => {
|
&TypeBound::Path(path, modifier) => {
|
||||||
match modifier {
|
match modifier {
|
||||||
TraitBoundModifier::None => (),
|
TraitBoundModifier::None => (),
|
||||||
TraitBoundModifier::Maybe => write!(f, "?")?,
|
TraitBoundModifier::Maybe => write!(f, "?")?,
|
||||||
}
|
}
|
||||||
path.hir_fmt(f, types_map)
|
types_map[path].hir_fmt(f, types_map)
|
||||||
}
|
}
|
||||||
TypeBound::Lifetime(lifetime) => {
|
TypeBound::Lifetime(lifetime) => {
|
||||||
write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
|
write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
|
||||||
|
@ -2079,7 +2079,7 @@ impl HirDisplayWithTypesMap for TypeBound {
|
||||||
"for<{}> ",
|
"for<{}> ",
|
||||||
lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
|
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) => {
|
TypeBound::Use(args) => {
|
||||||
let edition = f.edition();
|
let edition = f.edition();
|
||||||
|
|
|
@ -33,8 +33,8 @@ use hir_def::{
|
||||||
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
||||||
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
||||||
type_ref::{
|
type_ref::{
|
||||||
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
|
ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
|
||||||
TypeRefId, TypesMap, TypesSourceMap,
|
TypeRef, TypeRefId, TypesMap, TypesSourceMap,
|
||||||
},
|
},
|
||||||
AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
|
AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
|
||||||
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId,
|
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId,
|
||||||
|
@ -264,7 +264,8 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
}
|
}
|
||||||
TypeRef::Path(path) => {
|
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_;
|
res = res_;
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
@ -677,7 +678,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
|
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)
|
// Resolve the path (in type namespace)
|
||||||
if let Some(type_ref) = path.type_anchor() {
|
if let Some(type_ref) = path.type_anchor() {
|
||||||
let (ty, res) = self.lower_ty_ext(type_ref);
|
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() {
|
if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
|
||||||
// trait object type without dyn
|
// 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]);
|
let ty = self.lower_dyn_trait(&[bound]);
|
||||||
return (ty, None);
|
return (ty, None);
|
||||||
}
|
}
|
||||||
|
@ -998,7 +999,12 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
|
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)? {
|
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.
|
// FIXME(trait_alias): We need to handle trait alias here.
|
||||||
TypeNs::TraitId(tr) => tr,
|
TypeNs::TraitId(tr) => tr,
|
||||||
|
@ -1013,7 +1019,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
trait_ref: &HirTraitRef,
|
trait_ref: &HirTraitRef,
|
||||||
explicit_self_ty: Ty,
|
explicit_self_ty: Ty,
|
||||||
) -> Option<TraitRef> {
|
) -> 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(
|
fn trait_ref_substs_from_path(
|
||||||
|
@ -1072,11 +1078,11 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
|
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
|
||||||
let mut trait_ref = None;
|
let mut trait_ref = None;
|
||||||
let clause = match bound {
|
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 = self.lower_trait_ref_from_path(path, self_ty);
|
||||||
trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
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
|
let sized_trait = self
|
||||||
.db
|
.db
|
||||||
.lang_item(self.resolver.krate(), LangItem::Sized)
|
.lang_item(self.resolver.krate(), LangItem::Sized)
|
||||||
|
@ -1092,7 +1098,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
TypeBound::ForLifetime(_, path) => {
|
&TypeBound::ForLifetime(_, path) => {
|
||||||
// FIXME Don't silently drop the hrtb lifetimes here
|
// FIXME Don't silently drop the hrtb lifetimes here
|
||||||
trait_ref = self.lower_trait_ref_from_path(path, self_ty);
|
trait_ref = self.lower_trait_ref_from_path(path, self_ty);
|
||||||
trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
||||||
|
@ -1121,8 +1127,8 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
trait_ref: TraitRef,
|
trait_ref: TraitRef,
|
||||||
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
|
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
|
||||||
let last_segment = match bound {
|
let last_segment = match bound {
|
||||||
TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
|
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
|
||||||
path.segments().last()
|
self.types_map[path].segments().last()
|
||||||
}
|
}
|
||||||
TypeBound::Path(_, TraitBoundModifier::Maybe)
|
TypeBound::Path(_, TraitBoundModifier::Maybe)
|
||||||
| TypeBound::Use(_)
|
| TypeBound::Use(_)
|
||||||
|
@ -1593,9 +1599,10 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
}
|
}
|
||||||
|
|
||||||
match bound {
|
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
|
// Only lower the bound if the trait could possibly define the associated
|
||||||
// type we're looking for.
|
// type we're looking for.
|
||||||
|
let path = &ctx.types_map[path];
|
||||||
|
|
||||||
let Some(assoc_name) = &assoc_name else { return true };
|
let Some(assoc_name) = &assoc_name else { return true };
|
||||||
let Some(TypeNs::TraitId(tr)) =
|
let Some(TypeNs::TraitId(tr)) =
|
||||||
|
|
|
@ -18,13 +18,13 @@ use std::sync::LazyLock;
|
||||||
use base_db::SourceDatabaseFileInputExt as _;
|
use base_db::SourceDatabaseFileInputExt as _;
|
||||||
use expect_test::Expect;
|
use expect_test::Expect;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{Body, BodySourceMap, SyntheticSyntax},
|
body::{Body, BodySourceMap},
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
hir::{ExprId, Pat, PatId},
|
hir::{ExprId, Pat, PatId},
|
||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
|
AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, SyntheticSyntax,
|
||||||
};
|
};
|
||||||
use hir_expand::{db::ExpandDatabase, FileRange, InFile};
|
use hir_expand::{db::ExpandDatabase, FileRange, InFile};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
|
@ -185,7 +185,7 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match is_trait {
|
match is_trait {
|
||||||
true => bound.as_path(),
|
true => bound.as_path(&generic_params.types_map),
|
||||||
false => None,
|
false => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use hir_ty::{
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
pub use hir_def::VariantId;
|
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 hir_expand::{name::Name, HirFileId, InFile};
|
||||||
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
|
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
|
@ -132,12 +132,18 @@ impl HirDisplay for Function {
|
||||||
} else {
|
} else {
|
||||||
match &data.types_map[data.ret_type] {
|
match &data.types_map[data.ret_type] {
|
||||||
TypeRef::ImplTrait(bounds) => match &bounds[0] {
|
TypeRef::ImplTrait(bounds) => match &bounds[0] {
|
||||||
TypeBound::Path(path, _) => Some(
|
&TypeBound::Path(path, _) => Some(
|
||||||
*path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
|
*data.types_map[path]
|
||||||
[0]
|
.segments()
|
||||||
.type_ref
|
.iter()
|
||||||
.as_ref()
|
.last()
|
||||||
.unwrap(),
|
.unwrap()
|
||||||
|
.args_and_bindings
|
||||||
|
.unwrap()
|
||||||
|
.bindings[0]
|
||||||
|
.type_ref
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
),
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,7 +43,7 @@ use arrayvec::ArrayVec;
|
||||||
use base_db::{CrateDisplayName, CrateId, CrateOrigin};
|
use base_db::{CrateDisplayName, CrateId, CrateOrigin};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{BodyDiagnostic, SyntheticSyntax},
|
body::BodyDiagnostic,
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
||||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
|
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
|
||||||
|
@ -57,8 +57,8 @@ use hir_def::{
|
||||||
AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
|
AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
|
||||||
DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
|
DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
|
||||||
HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
|
HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
|
||||||
MacroExpander, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId,
|
MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId,
|
||||||
TypeOrConstParamId, TypeParamId, UnionId,
|
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
|
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
|
||||||
|
|
|
@ -13,8 +13,9 @@ use hir::{
|
||||||
ModuleDef, Name,
|
ModuleDef, Name,
|
||||||
};
|
};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{BodySourceMap, SyntheticSyntax},
|
body::BodySourceMap,
|
||||||
hir::{ExprId, PatId},
|
hir::{ExprId, PatId},
|
||||||
|
SyntheticSyntax,
|
||||||
};
|
};
|
||||||
use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
|
use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
|
||||||
use ide::{
|
use ide::{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue