Build source map for hir_def::TypeRefs

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:
Chayim Refael Friedman 2024-09-06 16:25:22 +03:00
parent 6a67a4d3cd
commit 89c0ffa6b0
40 changed files with 1712 additions and 778 deletions

View file

@ -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()))
}