Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/display.rs')
-rw-r--r--crates/hir-ty/src/display.rs181
1 files changed, 102 insertions, 79 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index f406666ae5..70c03477c4 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -33,7 +33,8 @@ use rustc_apfloat::{
Float,
};
use smallvec::SmallVec;
-use stdx::{never, IsNoneOr};
+use span::Edition;
+use stdx::never;
use triomphe::Arc;
use crate::{
@@ -131,7 +132,11 @@ pub trait HirDisplay {
/// Returns a `Display`able type that is human-readable.
/// Use this for showing types to the user (e.g. diagnostics)
- fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
+ fn display<'a>(
+ &'a self,
+ db: &'a dyn HirDatabase,
+ edition: Edition,
+ ) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
{
@@ -142,7 +147,7 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: false,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -153,6 +158,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
max_size: Option<usize>,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -164,7 +170,7 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: true,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -175,6 +181,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
limited_size: Option<usize>,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -186,7 +193,7 @@ pub trait HirDisplay {
limited_size,
omit_verbose_types: true,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds: false,
}
}
@@ -242,6 +249,7 @@ pub trait HirDisplay {
&'a self,
db: &'a dyn HirDatabase,
show_container_bounds: bool,
+ edition: Edition,
) -> HirDisplayWrapper<'a, Self>
where
Self: Sized,
@@ -253,13 +261,23 @@ pub trait HirDisplay {
limited_size: None,
omit_verbose_types: false,
closure_style: ClosureStyle::ImplFn,
- display_target: DisplayTarget::Diagnostics,
+ display_target: DisplayTarget::Diagnostics { edition },
show_container_bounds,
}
}
}
impl HirFormatter<'_> {
+ pub fn edition(&self) -> Edition {
+ match self.display_target {
+ DisplayTarget::Diagnostics { edition } => edition,
+ DisplayTarget::SourceCode { module_id, .. } => {
+ self.db.crate_graph()[module_id.krate()].edition
+ }
+ DisplayTarget::Test => Edition::CURRENT,
+ }
+ }
+
pub fn write_joined<T: HirDisplay>(
&mut self,
iter: impl IntoIterator<Item = T>,
@@ -324,7 +342,7 @@ pub enum DisplayTarget {
/// Display types for inlays, doc popups, autocompletion, etc...
/// Showing `{unknown}` or not qualifying paths is fine here.
/// There's no reason for this to fail.
- Diagnostics,
+ Diagnostics { edition: Edition },
/// Display types for inserting them in source files.
/// The generated code should compile, so paths need to be qualified.
SourceCode { module_id: ModuleId, allow_opaque: bool },
@@ -460,7 +478,7 @@ impl HirDisplay for ProjectionTy {
">::{}",
f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id))
.name
- .display(f.db.upcast())
+ .display(f.db.upcast(), f.edition())
)?;
let proj_params_count =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
@@ -499,7 +517,7 @@ impl HirDisplay for Const {
let id = from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics[id.local_id];
- write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?;
+ write!(f, "{}", param_data.name().unwrap().display(f.db.upcast(), f.edition()))?;
Ok(())
}
ConstValue::Concrete(c) => match &c.interned {
@@ -633,7 +651,7 @@ fn render_const_scalar(
TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.0 {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_data(s);
- write!(f, "&{}", data.name.display(f.db.upcast()))?;
+ write!(f, "&{}", data.name.display(f.db.upcast(), f.edition()))?;
Ok(())
}
_ => f.write_str("<unsized-enum-or-union>"),
@@ -691,7 +709,7 @@ fn render_const_scalar(
match adt.0 {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_data(s);
- write!(f, "{}", data.name.display(f.db.upcast()))?;
+ write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?;
let field_types = f.db.field_types(s.into());
render_variant_after_name(
&data.variant_data,
@@ -705,7 +723,7 @@ fn render_const_scalar(
)
}
hir_def::AdtId::UnionId(u) => {
- write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast()))
+ write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast(), f.edition()))
}
hir_def::AdtId::EnumId(e) => {
let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else {
@@ -717,7 +735,7 @@ fn render_const_scalar(
return f.write_str("<failed-to-detect-variant>");
};
let data = f.db.enum_variant_data(var_id);
- write!(f, "{}", data.name.display(f.db.upcast()))?;
+ write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?;
let field_types = f.db.field_types(var_id.into());
render_variant_after_name(
&data.variant_data,
@@ -802,11 +820,11 @@ fn render_variant_after_name(
if matches!(data, VariantData::Record(_)) {
write!(f, " {{")?;
if let Some((id, data)) = it.next() {
- write!(f, " {}: ", data.name.display(f.db.upcast()))?;
+ write!(f, " {}: ", data.name.display(f.db.upcast(), f.edition()))?;
render_field(f, id)?;
}
for (id, data) in it {
- write!(f, ", {}: ", data.name.display(f.db.upcast()))?;
+ write!(f, ", {}: ", data.name.display(f.db.upcast(), f.edition()))?;
render_field(f, id)?;
}
write!(f, " }}")?;
@@ -1000,15 +1018,23 @@ impl HirDisplay for Ty {
CallableDefId::FunctionId(ff) => {
write!(f, "fn ")?;
f.start_location_link(def.into());
- write!(f, "{}", db.function_data(ff).name.display(f.db.upcast()))?
+ write!(
+ f,
+ "{}",
+ db.function_data(ff).name.display(f.db.upcast(), f.edition())
+ )?
}
CallableDefId::StructId(s) => {
f.start_location_link(def.into());
- write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
+ write!(f, "{}", db.struct_data(s).name.display(f.db.upcast(), f.edition()))?
}
CallableDefId::EnumVariantId(e) => {
f.start_location_link(def.into());
- write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
+ write!(
+ f,
+ "{}",
+ db.enum_variant_data(e).name.display(f.db.upcast(), f.edition())
+ )?
}
};
f.end_location_link();
@@ -1019,26 +1045,25 @@ impl HirDisplay for Ty {
let (parent_len, self_param, type_, const_, impl_, lifetime) =
generics.provenance_split();
let parameters = parameters.as_slice(Interner);
+ debug_assert_eq!(
+ parameters.len(),
+ parent_len + self_param as usize + type_ + const_ + impl_ + lifetime
+ );
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
if parameters.len() - impl_ > 0 {
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
+ let parameters =
+ generic_args_sans_defaults(f, Some(generic_def_id), parameters);
let without_impl = self_param as usize + type_ + const_ + lifetime;
// parent's params (those from enclosing impl or trait, if any).
let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
- debug_assert_eq!(parent_params.len(), parent_len);
-
- let parent_params =
- generic_args_sans_defaults(f, Some(generic_def_id), parent_params);
- let fn_params =
- &generic_args_sans_defaults(f, Some(generic_def_id), fn_params)
- [0..without_impl];
write!(f, "<")?;
hir_fmt_generic_arguments(f, parent_params, None)?;
if !parent_params.is_empty() && !fn_params.is_empty() {
write!(f, ", ")?;
}
- hir_fmt_generic_arguments(f, fn_params, None)?;
+ hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?;
write!(f, ">")?;
}
}
@@ -1054,13 +1079,13 @@ impl HirDisplay for Ty {
TyKind::Adt(AdtId(def_id), parameters) => {
f.start_location_link((*def_id).into());
match f.display_target {
- DisplayTarget::Diagnostics | DisplayTarget::Test => {
+ DisplayTarget::Diagnostics { .. } | DisplayTarget::Test => {
let name = match *def_id {
hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(),
hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(),
hir_def::AdtId::EnumId(it) => db.enum_data(it).name.clone(),
};
- write!(f, "{}", name.display(f.db.upcast()))?;
+ write!(f, "{}", name.display(f.db.upcast(), f.edition()))?;
}
DisplayTarget::SourceCode { module_id, allow_opaque: _ } => {
if let Some(path) = find_path::find_path(
@@ -1076,7 +1101,7 @@ impl HirDisplay for Ty {
prefer_absolute: false,
},
) {
- write!(f, "{}", path.display(f.db.upcast()))?;
+ write!(f, "{}", path.display(f.db.upcast(), f.edition()))?;
} else {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::PathNotFound,
@@ -1102,12 +1127,12 @@ impl HirDisplay for Ty {
// Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
if f.display_target.is_test() {
f.start_location_link(trait_.into());
- write!(f, "{}", trait_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", trait_data.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
write!(f, "::")?;
f.start_location_link(type_alias.into());
- write!(f, "{}", type_alias_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias_data.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
// Note that the generic args for the associated type come before those for the
// trait (including the self type).
@@ -1125,7 +1150,7 @@ impl HirDisplay for Ty {
let alias = from_foreign_def_id(*type_alias);
let type_alias = db.type_alias_data(alias);
f.start_location_link(alias.into());
- write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
}
TyKind::OpaqueType(opaque_ty_id, parameters) => {
@@ -1257,7 +1282,10 @@ impl HirDisplay for Ty {
write!(
f,
"{}",
- p.name.clone().unwrap_or_else(Name::missing).display(f.db.upcast())
+ p.name
+ .clone()
+ .unwrap_or_else(Name::missing)
+ .display(f.db.upcast(), f.edition())
)?
}
TypeParamProvenance::ArgumentImplTrait => {
@@ -1290,7 +1318,7 @@ impl HirDisplay for Ty {
}
},
TypeOrConstParamData::ConstParamData(p) => {
- write!(f, "{}", p.name.display(f.db.upcast()))?;
+ write!(f, "{}", p.name.display(f.db.upcast(), f.edition()))?;
}
}
}
@@ -1410,17 +1438,7 @@ fn hir_fmt_generics(
let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);
- // FIXME: Remote this
- // most of our lifetimes will be errors as we lack elision and inference
- // so don't render them for now
- let only_err_lifetimes = !cfg!(test)
- && parameters_to_write.iter().all(|arg| {
- matches!(
- arg.data(Interner),
- chalk_ir::GenericArgData::Lifetime(it) if *it.data(Interner) == LifetimeData::Error
- )
- });
- if !parameters_to_write.is_empty() && !only_err_lifetimes {
+ if !parameters_to_write.is_empty() {
write!(f, "<")?;
hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
write!(f, ">")?;
@@ -1461,12 +1479,14 @@ fn generic_args_sans_defaults<'ga>(
}
// otherwise, if the arg is equal to the param default, hide it (unless the
// default is an error which can happen for the trait Self type)
- #[allow(unstable_name_collisions)]
- IsNoneOr::is_none_or(default_parameters.get(i), |default_parameter| {
- // !is_err(default_parameter.skip_binders())
- // &&
- arg != &default_parameter.clone().substitute(Interner, &parameters)
- })
+ match default_parameters.get(i) {
+ None => true,
+ Some(default_parameter) => {
+ // !is_err(default_parameter.skip_binders())
+ // &&
+ arg != &default_parameter.clone().substitute(Interner, &parameters)
+ }
+ }
};
let mut default_from = 0;
for (i, parameter) in parameters.iter().enumerate() {
@@ -1495,18 +1515,6 @@ fn hir_fmt_generic_arguments(
None => (parameters, &[][..]),
};
for generic_arg in lifetimes.iter().chain(ty_or_const) {
- // FIXME: Remove this
- // most of our lifetimes will be errors as we lack elision and inference
- // so don't render them for now
- if !cfg!(test)
- && matches!(
- generic_arg.lifetime(Interner),
- Some(l) if ***l.interned() == LifetimeData::Error
- )
- {
- continue;
- }
-
if !mem::take(&mut first) {
write!(f, ", ")?;
}
@@ -1633,7 +1641,7 @@ fn write_bounds_like_dyn_trait(
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
+ write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
if is_fn_trait {
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
@@ -1707,7 +1715,7 @@ fn write_bounds_like_dyn_trait(
let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
let type_alias = f.db.type_alias_data(assoc_ty_id);
f.start_location_link(assoc_ty_id.into());
- write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
+ write!(f, "{}", type_alias.name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
@@ -1771,7 +1779,7 @@ fn fmt_trait_ref(
}
let trait_ = tr.hir_trait_id();
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
+ write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
f.end_location_link();
let substs = tr.substitution.as_slice(Interner);
hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
@@ -1797,7 +1805,11 @@ impl HirDisplay for WhereClause {
write!(f, ">::",)?;
let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
f.start_location_link(type_alias.into());
- write!(f, "{}", f.db.type_alias_data(type_alias).name.display(f.db.upcast()),)?;
+ write!(
+ f,
+ "{}",
+ f.db.type_alias_data(type_alias).name.display(f.db.upcast(), f.edition()),
+ )?;
f.end_location_link();
write!(f, " = ")?;
ty.hir_fmt(f)?;
@@ -1833,14 +1845,20 @@ impl HirDisplay for LifetimeData {
let id = lt_from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics[id.local_id];
- write!(f, "{}", param_data.name.display(f.db.upcast()))?;
+ write!(f, "{}", param_data.name.display(f.db.upcast(), f.edition()))?;
Ok(())
}
_ if f.display_target.is_source_code() => write!(f, "'_"),
LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
LifetimeData::InferenceVar(_) => write!(f, "_"),
LifetimeData::Static => write!(f, "'static"),
- LifetimeData::Error => write!(f, "'?"),
+ LifetimeData::Error => {
+ if cfg!(test) {
+ write!(f, "'?")
+ } else {
+ write!(f, "'_")
+ }
+ }
LifetimeData::Erased => write!(f, "'<erased>"),
LifetimeData::Phantom(void, _) => match *void {},
}
@@ -1855,7 +1873,7 @@ impl HirDisplay for DomainGoal {
wc.hir_fmt(f)?;
write!(f, ")")?;
}
- _ => write!(f, "?")?,
+ _ => write!(f, "_")?,
}
Ok(())
}
@@ -1914,7 +1932,7 @@ impl HirDisplay for TypeRef {
};
write!(f, "&")?;
if let Some(lifetime) = lifetime {
- write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
+ write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
}
write!(f, "{mutability}")?;
inner.hir_fmt(f)?;
@@ -1922,7 +1940,7 @@ impl HirDisplay for TypeRef {
TypeRef::Array(inner, len) => {
write!(f, "[")?;
inner.hir_fmt(f)?;
- write!(f, "; {}]", len.display(f.db.upcast()))?;
+ write!(f, "; {}]", len.display(f.db.upcast(), f.edition()))?;
}
TypeRef::Slice(inner) => {
write!(f, "[")?;
@@ -1943,7 +1961,7 @@ impl HirDisplay for TypeRef {
for index in 0..function_parameters.len() {
let (param_name, param_type) = &function_parameters[index];
if let Some(name) = param_name {
- write!(f, "{}: ", name.display(f.db.upcast()))?;
+ write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?;
}
param_type.hir_fmt(f)?;
@@ -2001,12 +2019,15 @@ impl HirDisplay for TypeBound {
}
path.hir_fmt(f)
}
- TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name.display(f.db.upcast())),
+ TypeBound::Lifetime(lifetime) => {
+ write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
+ }
TypeBound::ForLifetime(lifetimes, path) => {
+ let edition = f.edition();
write!(
f,
"for<{}> ",
- lifetimes.iter().map(|it| it.display(f.db.upcast())).format(", ")
+ lifetimes.iter().map(|it| it.display(f.db.upcast(), edition)).format(", ")
)?;
path.hir_fmt(f)
}
@@ -2072,7 +2093,7 @@ impl HirDisplay for Path {
if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
write!(f, "::")?;
}
- write!(f, "{}", segment.name.display(f.db.upcast()))?;
+ write!(f, "{}", segment.name.display(f.db.upcast(), f.edition()))?;
if let Some(generic_args) = segment.args_and_bindings {
// We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
// Do we actually format expressions?
@@ -2117,7 +2138,7 @@ impl HirDisplay for Path {
} else {
write!(f, ", ")?;
}
- write!(f, "{}", binding.name.display(f.db.upcast()))?;
+ write!(f, "{}", binding.name.display(f.db.upcast(), f.edition()))?;
match &binding.type_ref {
Some(ty) => {
write!(f, " = ")?;
@@ -2151,9 +2172,11 @@ impl HirDisplay for hir_def::path::GenericArg {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self {
hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
- hir_def::path::GenericArg::Const(c) => write!(f, "{}", c.display(f.db.upcast())),
+ hir_def::path::GenericArg::Const(c) => {
+ write!(f, "{}", c.display(f.db.upcast(), f.edition()))
+ }
hir_def::path::GenericArg::Lifetime(lifetime) => {
- write!(f, "{}", lifetime.name.display(f.db.upcast()))
+ write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
}
}
}