mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
Build source map for hir_def::TypeRef
s
So that given a `TypeRef` we will be able to trace it back to source code. This is necessary to be able to provide diagnostics for lowering to chalk tys, since the input to that is `TypeRef`. This means that `TypeRef`s now have an identity, which means storing them in arena and not interning them, which is an unfortunate (but necessary) loss but also a pretty massive change. Luckily, because of the separation layer we have for IDE and HIR, this change never crosses the IDE boundary.
This commit is contained in:
parent
6a67a4d3cd
commit
89c0ffa6b0
40 changed files with 1712 additions and 778 deletions
|
@ -19,7 +19,9 @@ use hir_def::{
|
|||
lang_item::{LangItem, LangItemTarget},
|
||||
nameres::DefMap,
|
||||
path::{Path, PathKind},
|
||||
type_ref::{TraitBoundModifier, TypeBound, TypeRef, UseArgRef},
|
||||
type_ref::{
|
||||
TraitBoundModifier, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap, UseArgRef,
|
||||
},
|
||||
visibility::Visibility,
|
||||
GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId,
|
||||
ModuleId, TraitId,
|
||||
|
@ -806,7 +808,7 @@ fn render_variant_after_name(
|
|||
memory_map: &MemoryMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match data {
|
||||
VariantData::Record(fields) | VariantData::Tuple(fields) => {
|
||||
VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => {
|
||||
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
|
||||
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
|
||||
let ty = field_types[id].clone().substitute(Interner, subst);
|
||||
|
@ -817,7 +819,7 @@ fn render_variant_after_name(
|
|||
render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)
|
||||
};
|
||||
let mut it = fields.iter();
|
||||
if matches!(data, VariantData::Record(_)) {
|
||||
if matches!(data, VariantData::Record { .. }) {
|
||||
write!(f, " {{")?;
|
||||
if let Some((id, data)) = it.next() {
|
||||
write!(f, " {}: ", data.name.display(f.db.upcast(), f.edition()))?;
|
||||
|
@ -1897,27 +1899,70 @@ pub fn write_visibility(
|
|||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for TypeRef {
|
||||
pub trait HirDisplayWithTypesMap {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError>;
|
||||
}
|
||||
|
||||
impl<T: ?Sized + HirDisplayWithTypesMap> HirDisplayWithTypesMap for &'_ T {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
T::hir_fmt(&**self, f, types_map)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hir_display_with_types_map<'a, T: HirDisplayWithTypesMap + 'a>(
|
||||
value: T,
|
||||
types_map: &'a TypesMap,
|
||||
) -> impl HirDisplay + 'a {
|
||||
TypesMapAdapter(value, types_map)
|
||||
}
|
||||
|
||||
struct TypesMapAdapter<'a, T>(T, &'a TypesMap);
|
||||
|
||||
impl<'a, T> TypesMapAdapter<'a, T> {
|
||||
fn wrap(types_map: &'a TypesMap) -> impl Fn(T) -> TypesMapAdapter<'a, T> {
|
||||
move |value| TypesMapAdapter(value, types_map)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HirDisplayWithTypesMap> HirDisplay for TypesMapAdapter<'_, T> {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
match self {
|
||||
T::hir_fmt(&self.0, f, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl HirDisplayWithTypesMap for TypeRefId {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match &types_map[*self] {
|
||||
TypeRef::Never => write!(f, "!")?,
|
||||
TypeRef::Placeholder => write!(f, "_")?,
|
||||
TypeRef::Tuple(elems) => {
|
||||
write!(f, "(")?;
|
||||
f.write_joined(elems, ", ")?;
|
||||
f.write_joined(elems.iter().map(TypesMapAdapter::wrap(types_map)), ", ")?;
|
||||
if elems.len() == 1 {
|
||||
write!(f, ",")?;
|
||||
}
|
||||
write!(f, ")")?;
|
||||
}
|
||||
TypeRef::Path(path) => path.hir_fmt(f)?,
|
||||
TypeRef::Path(path) => path.hir_fmt(f, types_map)?,
|
||||
TypeRef::RawPtr(inner, mutability) => {
|
||||
let mutability = match mutability {
|
||||
hir_def::type_ref::Mutability::Shared => "*const ",
|
||||
hir_def::type_ref::Mutability::Mut => "*mut ",
|
||||
};
|
||||
write!(f, "{mutability}")?;
|
||||
inner.hir_fmt(f)?;
|
||||
inner.hir_fmt(f, types_map)?;
|
||||
}
|
||||
TypeRef::Reference(inner, lifetime, mutability) => {
|
||||
let mutability = match mutability {
|
||||
|
@ -1929,19 +1974,19 @@ impl HirDisplay for TypeRef {
|
|||
write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
|
||||
}
|
||||
write!(f, "{mutability}")?;
|
||||
inner.hir_fmt(f)?;
|
||||
inner.hir_fmt(f, types_map)?;
|
||||
}
|
||||
TypeRef::Array(inner, len) => {
|
||||
write!(f, "[")?;
|
||||
inner.hir_fmt(f)?;
|
||||
inner.hir_fmt(f, types_map)?;
|
||||
write!(f, "; {}]", len.display(f.db.upcast(), f.edition()))?;
|
||||
}
|
||||
TypeRef::Slice(inner) => {
|
||||
write!(f, "[")?;
|
||||
inner.hir_fmt(f)?;
|
||||
inner.hir_fmt(f, types_map)?;
|
||||
write!(f, "]")?;
|
||||
}
|
||||
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe, ref abi) => {
|
||||
&TypeRef::Fn { params: ref parameters, is_varargs, is_unsafe, ref abi } => {
|
||||
if is_unsafe {
|
||||
write!(f, "unsafe ")?;
|
||||
}
|
||||
|
@ -1958,7 +2003,7 @@ impl HirDisplay for TypeRef {
|
|||
write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?;
|
||||
}
|
||||
|
||||
param_type.hir_fmt(f)?;
|
||||
param_type.hir_fmt(f, types_map)?;
|
||||
|
||||
if index != function_parameters.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
|
@ -1968,29 +2013,36 @@ impl HirDisplay for TypeRef {
|
|||
write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
|
||||
}
|
||||
write!(f, ")")?;
|
||||
match &return_type {
|
||||
match &types_map[*return_type] {
|
||||
TypeRef::Tuple(tup) if tup.is_empty() => {}
|
||||
_ => {
|
||||
write!(f, " -> ")?;
|
||||
return_type.hir_fmt(f)?;
|
||||
return_type.hir_fmt(f, types_map)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeRef::ImplTrait(bounds) => {
|
||||
write!(f, "impl ")?;
|
||||
f.write_joined(bounds, " + ")?;
|
||||
f.write_joined(bounds.iter().map(TypesMapAdapter::wrap(types_map)), " + ")?;
|
||||
}
|
||||
TypeRef::DynTrait(bounds) => {
|
||||
write!(f, "dyn ")?;
|
||||
f.write_joined(bounds, " + ")?;
|
||||
f.write_joined(bounds.iter().map(TypesMapAdapter::wrap(types_map)), " + ")?;
|
||||
}
|
||||
TypeRef::Macro(macro_call) => {
|
||||
let ctx = hir_def::lower::LowerCtx::new(f.db.upcast(), macro_call.file_id);
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx = hir_def::lower::LowerCtx::new(
|
||||
f.db.upcast(),
|
||||
macro_call.file_id,
|
||||
&mut types_map,
|
||||
&mut types_source_map,
|
||||
);
|
||||
let macro_call = macro_call.to_node(f.db.upcast());
|
||||
match macro_call.path() {
|
||||
Some(path) => match Path::from_src(&ctx, path) {
|
||||
Some(path) => path.hir_fmt(f)?,
|
||||
Some(path) => path.hir_fmt(f, &types_map)?,
|
||||
None => write!(f, "{{macro}}")?,
|
||||
},
|
||||
None => write!(f, "{{macro}}")?,
|
||||
|
@ -2003,15 +2055,19 @@ impl HirDisplay for TypeRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for TypeBound {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
impl HirDisplayWithTypesMap for TypeBound {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match self {
|
||||
TypeBound::Path(path, modifier) => {
|
||||
match modifier {
|
||||
TraitBoundModifier::None => (),
|
||||
TraitBoundModifier::Maybe => write!(f, "?")?,
|
||||
}
|
||||
path.hir_fmt(f)
|
||||
path.hir_fmt(f, types_map)
|
||||
}
|
||||
TypeBound::Lifetime(lifetime) => {
|
||||
write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
|
||||
|
@ -2023,7 +2079,7 @@ impl HirDisplay for TypeBound {
|
|||
"for<{}> ",
|
||||
lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
|
||||
)?;
|
||||
path.hir_fmt(f)
|
||||
path.hir_fmt(f, types_map)
|
||||
}
|
||||
TypeBound::Use(args) => {
|
||||
let edition = f.edition();
|
||||
|
@ -2043,12 +2099,16 @@ impl HirDisplay for TypeBound {
|
|||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for Path {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
impl HirDisplayWithTypesMap for Path {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match (self.type_anchor(), self.kind()) {
|
||||
(Some(anchor), _) => {
|
||||
write!(f, "<")?;
|
||||
anchor.hir_fmt(f)?;
|
||||
anchor.hir_fmt(f, types_map)?;
|
||||
write!(f, ">")?;
|
||||
}
|
||||
(_, PathKind::Plain) => {}
|
||||
|
@ -2091,7 +2151,7 @@ impl HirDisplay for Path {
|
|||
});
|
||||
if let Some(ty) = trait_self_ty {
|
||||
write!(f, "<")?;
|
||||
ty.hir_fmt(f)?;
|
||||
ty.hir_fmt(f, types_map)?;
|
||||
write!(f, " as ")?;
|
||||
// Now format the path of the trait...
|
||||
}
|
||||
|
@ -2107,21 +2167,26 @@ impl HirDisplay for Path {
|
|||
if generic_args.desugared_from_fn {
|
||||
// First argument will be a tuple, which already includes the parentheses.
|
||||
// If the tuple only contains 1 item, write it manually to avoid the trailing `,`.
|
||||
if let hir_def::path::GenericArg::Type(TypeRef::Tuple(v)) =
|
||||
&generic_args.args[0]
|
||||
{
|
||||
let tuple = match generic_args.args[0] {
|
||||
hir_def::path::GenericArg::Type(ty) => match &types_map[ty] {
|
||||
TypeRef::Tuple(it) => Some(it),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
if let Some(v) = tuple {
|
||||
if v.len() == 1 {
|
||||
write!(f, "(")?;
|
||||
v[0].hir_fmt(f)?;
|
||||
v[0].hir_fmt(f, types_map)?;
|
||||
write!(f, ")")?;
|
||||
} else {
|
||||
generic_args.args[0].hir_fmt(f)?;
|
||||
generic_args.args[0].hir_fmt(f, types_map)?;
|
||||
}
|
||||
}
|
||||
if let Some(ret) = &generic_args.bindings[0].type_ref {
|
||||
if !matches!(ret, TypeRef::Tuple(v) if v.is_empty()) {
|
||||
if let Some(ret) = generic_args.bindings[0].type_ref {
|
||||
if !matches!(&types_map[ret], TypeRef::Tuple(v) if v.is_empty()) {
|
||||
write!(f, " -> ")?;
|
||||
ret.hir_fmt(f)?;
|
||||
ret.hir_fmt(f, types_map)?;
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
|
@ -2136,7 +2201,7 @@ impl HirDisplay for Path {
|
|||
} else {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
arg.hir_fmt(f)?;
|
||||
arg.hir_fmt(f, types_map)?;
|
||||
}
|
||||
for binding in generic_args.bindings.iter() {
|
||||
if first {
|
||||
|
@ -2149,11 +2214,14 @@ impl HirDisplay for Path {
|
|||
match &binding.type_ref {
|
||||
Some(ty) => {
|
||||
write!(f, " = ")?;
|
||||
ty.hir_fmt(f)?
|
||||
ty.hir_fmt(f, types_map)?
|
||||
}
|
||||
None => {
|
||||
write!(f, ": ")?;
|
||||
f.write_joined(binding.bounds.iter(), " + ")?;
|
||||
f.write_joined(
|
||||
binding.bounds.iter().map(TypesMapAdapter::wrap(types_map)),
|
||||
" + ",
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2175,10 +2243,14 @@ impl HirDisplay for Path {
|
|||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for hir_def::path::GenericArg {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
impl HirDisplayWithTypesMap for hir_def::path::GenericArg {
|
||||
fn hir_fmt(
|
||||
&self,
|
||||
f: &mut HirFormatter<'_>,
|
||||
types_map: &TypesMap,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
match self {
|
||||
hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
|
||||
hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f, types_map),
|
||||
hir_def::path::GenericArg::Const(c) => {
|
||||
write!(f, "{}", c.display(f.db.upcast(), f.edition()))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue