summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-ty/src/display.rs')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs236
1 files changed, 144 insertions, 92 deletions
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 66e813eed..b22064d8c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -11,17 +11,17 @@ use hir_def::{
db::DefDatabase,
find_path,
generics::{TypeOrConstParamData, TypeParamProvenance},
- intern::{Internable, Interned},
item_scope::ItemInNs,
+ lang_item::{LangItem, LangItemTarget},
path::{Path, PathKind},
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility,
HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
};
use hir_expand::{hygiene::Hygiene, name::Name};
+use intern::{Internable, Interned};
use itertools::Itertools;
use smallvec::SmallVec;
-use syntax::SmolStr;
use crate::{
db::HirDatabase,
@@ -325,7 +325,7 @@ impl HirDisplay for ProjectionTy {
let trait_ref = self.trait_ref(f.db);
write!(f, "<")?;
- fmt_trait_ref(&trait_ref, f, true)?;
+ fmt_trait_ref(f, &trait_ref, true)?;
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
let proj_params_count =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
@@ -383,7 +383,10 @@ impl HirDisplay for BoundVar {
}
impl HirDisplay for Ty {
- fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(
+ &self,
+ f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
+ ) -> Result<(), HirDisplayError> {
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
}
@@ -434,7 +437,7 @@ impl HirDisplay for Ty {
bounds.iter().any(|bound| {
if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
let trait_ = trait_ref.hir_trait_id();
- fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
+ fn_traits(db.upcast(), trait_).any(|it| it == trait_)
} else {
false
}
@@ -450,22 +453,20 @@ impl HirDisplay for Ty {
substitution: parameters,
}))
| TyKind::OpaqueType(opaque_ty_id, parameters) => {
- let impl_trait_id =
- f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
- let datas =
- f.db.return_type_impl_traits(func)
- .expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ let datas = db
+ .return_type_impl_traits(func)
+ .expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, parameters);
let mut len = bounds.skip_binders().len();
// Don't count Sized but count when it absent
// (i.e. when explicit ?Sized bound is set).
let default_sized = SizedByDefault::Sized {
- anchor: func.lookup(f.db.upcast()).module(f.db.upcast()).krate(),
+ anchor: func.lookup(db.upcast()).module(db.upcast()).krate(),
};
let sized_bounds = bounds
.skip_binders()
@@ -476,7 +477,7 @@ impl HirDisplay for Ty {
WhereClause::Implemented(trait_ref)
if default_sized.is_sized_trait(
trait_ref.hir_trait_id(),
- f.db.upcast(),
+ db.upcast(),
),
)
})
@@ -524,19 +525,19 @@ impl HirDisplay for Ty {
sig.hir_fmt(f)?;
}
TyKind::FnDef(def, parameters) => {
- let def = from_chalk(f.db, *def);
- let sig = f.db.callable_item_signature(def).substitute(Interner, parameters);
+ let def = from_chalk(db, *def);
+ let sig = db.callable_item_signature(def).substitute(Interner, parameters);
+ f.start_location_link(def.into());
match def {
- CallableDefId::FunctionId(ff) => {
- write!(f, "fn {}", f.db.function_data(ff).name)?
- }
- CallableDefId::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?,
+ CallableDefId::FunctionId(ff) => write!(f, "fn {}", db.function_data(ff).name)?,
+ CallableDefId::StructId(s) => write!(f, "{}", db.struct_data(s).name)?,
CallableDefId::EnumVariantId(e) => {
- write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
+ write!(f, "{}", db.enum_data(e.parent).variants[e.local_id].name)?
}
};
+ f.end_location_link();
if parameters.len(Interner) > 0 {
- let generics = generics(f.db.upcast(), def.into());
+ let generics = generics(db.upcast(), def.into());
let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
generics.provenance_split();
let total_len = parent_params + self_param + type_params + const_params;
@@ -568,15 +569,15 @@ impl HirDisplay for Ty {
match f.display_target {
DisplayTarget::Diagnostics | DisplayTarget::Test => {
let name = match *def_id {
- hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
- hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
- hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
+ 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}")?;
}
DisplayTarget::SourceCode { module_id } => {
if let Some(path) = find_path::find_path(
- f.db.upcast(),
+ db.upcast(),
ItemInNs::Types((*def_id).into()),
module_id,
false,
@@ -596,8 +597,8 @@ impl HirDisplay for Ty {
|| f.omit_verbose_types()
{
match self
- .as_generic_def(f.db)
- .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
+ .as_generic_def(db)
+ .map(|generic_def_id| db.generic_defaults(generic_def_id))
.filter(|defaults| !defaults.is_empty())
{
None => parameters.as_slice(Interner),
@@ -669,16 +670,23 @@ impl HirDisplay for Ty {
}
TyKind::AssociatedType(assoc_type_id, parameters) => {
let type_alias = from_assoc_type_id(*assoc_type_id);
- let trait_ = match type_alias.lookup(f.db.upcast()).container {
+ let trait_ = match type_alias.lookup(db.upcast()).container {
ItemContainerId::TraitId(it) => it,
_ => panic!("not an associated type"),
};
- let trait_ = f.db.trait_data(trait_);
- let type_alias_data = f.db.type_alias_data(type_alias);
+ let trait_data = db.trait_data(trait_);
+ let type_alias_data = db.type_alias_data(type_alias);
// 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() {
- write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
+ f.start_location_link(trait_.into());
+ write!(f, "{}", trait_data.name)?;
+ f.end_location_link();
+ write!(f, "::")?;
+
+ f.start_location_link(type_alias.into());
+ write!(f, "{}", type_alias_data.name)?;
+ f.end_location_link();
// Note that the generic args for the associated type come before those for the
// trait (including the self type).
// FIXME: reconsider the generic args order upon formatting?
@@ -697,30 +705,54 @@ impl HirDisplay for Ty {
}
}
TyKind::Foreign(type_alias) => {
- let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
+ 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)?;
+ f.end_location_link();
}
TyKind::OpaqueType(opaque_ty_id, parameters) => {
- let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas =
- f.db.return_type_impl_traits(func).expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ db.return_type_impl_traits(func).expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &parameters);
- let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
+ let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
- f,
)?;
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
}
- ImplTraitId::AsyncBlockTypeImplTrait(..) => {
- write!(f, "impl Future<Output = ")?;
+ ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
+ let future_trait = db
+ .lang_item(body.module(db.upcast()).krate(), LangItem::Future)
+ .and_then(LangItemTarget::as_trait);
+ let output = future_trait.and_then(|t| {
+ db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output))
+ });
+ write!(f, "impl ")?;
+ if let Some(t) = future_trait {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Future")?;
+ if let Some(_) = future_trait {
+ f.end_location_link();
+ }
+ write!(f, "<")?;
+ if let Some(t) = output {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Output")?;
+ if let Some(_) = output {
+ f.end_location_link();
+ }
+ write!(f, " = ")?;
parameters.at(Interner, 0).hir_fmt(f)?;
write!(f, ">")?;
}
@@ -732,7 +764,7 @@ impl HirDisplay for Ty {
DisplaySourceCodeError::Closure,
));
}
- let sig = substs.at(Interner, 0).assert_ty_ref(Interner).callable_sig(f.db);
+ let sig = substs.at(Interner, 0).assert_ty_ref(Interner).callable_sig(db);
if let Some(sig) = sig {
if sig.params().is_empty() {
write!(f, "||")?;
@@ -751,8 +783,8 @@ impl HirDisplay for Ty {
}
}
TyKind::Placeholder(idx) => {
- let id = from_placeholder_idx(f.db, *idx);
- let generics = generics(f.db.upcast(), id.parent);
+ let id = from_placeholder_idx(db, *idx);
+ let generics = generics(db.upcast(), id.parent);
let param_data = &generics.params.type_or_consts[id.local_id];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
@@ -760,28 +792,28 @@ impl HirDisplay for Ty {
write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
- let substs = generics.placeholder_subst(f.db);
- let bounds =
- f.db.generic_predicates(id.parent)
- .iter()
- .map(|pred| pred.clone().substitute(Interner, &substs))
- .filter(|wc| match &wc.skip_binders() {
- WhereClause::Implemented(tr) => {
- &tr.self_type_parameter(Interner) == self
- }
- WhereClause::AliasEq(AliasEq {
- alias: AliasTy::Projection(proj),
- ty: _,
- }) => &proj.self_type_parameter(f.db) == self,
- _ => false,
- })
- .collect::<Vec<_>>();
- let krate = id.parent.module(f.db.upcast()).krate();
+ let substs = generics.placeholder_subst(db);
+ let bounds = db
+ .generic_predicates(id.parent)
+ .iter()
+ .map(|pred| pred.clone().substitute(Interner, &substs))
+ .filter(|wc| match &wc.skip_binders() {
+ WhereClause::Implemented(tr) => {
+ &tr.self_type_parameter(Interner) == self
+ }
+ WhereClause::AliasEq(AliasEq {
+ alias: AliasTy::Projection(proj),
+ ty: _,
+ }) => &proj.self_type_parameter(db) == self,
+ _ => false,
+ })
+ .collect::<Vec<_>>();
+ let krate = id.parent.module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
&bounds,
SizedByDefault::Sized { anchor: krate },
- f,
)?;
}
},
@@ -803,29 +835,28 @@ impl HirDisplay for Ty {
bounds.extend(auto_traits);
write_bounds_like_dyn_trait_with_prefix(
+ f,
"dyn",
&bounds,
SizedByDefault::NotSized,
- f,
)?;
}
TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
- let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas =
- f.db.return_type_impl_traits(func).expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ db.return_type_impl_traits(func).expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &opaque_ty.substitution);
- let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
+ let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
- f,
)?;
}
ImplTraitId::AsyncBlockTypeImplTrait(..) => {
@@ -848,7 +879,6 @@ impl HirDisplay for Ty {
DisplaySourceCodeError::Generator,
));
}
-
let subst = subst.as_slice(Interner);
let a: Option<SmallVec<[&Ty; 3]>> = subst
.get(subst.len() - 3..)
@@ -897,7 +927,7 @@ impl HirDisplay for CallableSig {
}
}
-fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
+fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
let krate = trait_.lookup(db).container.krate();
utils::fn_traits(db, krate)
}
@@ -914,7 +944,7 @@ impl SizedByDefault {
Self::NotSized => false,
Self::Sized { anchor } => {
let sized_trait = db
- .lang_item(anchor, SmolStr::new_inline("sized"))
+ .lang_item(anchor, LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait());
Some(trait_) == sized_trait
}
@@ -923,26 +953,26 @@ impl SizedByDefault {
}
pub fn write_bounds_like_dyn_trait_with_prefix(
+ f: &mut HirFormatter<'_>,
prefix: &str,
predicates: &[QuantifiedWhereClause],
default_sized: SizedByDefault,
- f: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
write!(f, "{prefix}")?;
if !predicates.is_empty()
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
{
write!(f, " ")?;
- write_bounds_like_dyn_trait(predicates, default_sized, f)
+ write_bounds_like_dyn_trait(f, predicates, default_sized)
} else {
Ok(())
}
}
fn write_bounds_like_dyn_trait(
+ f: &mut HirFormatter<'_>,
predicates: &[QuantifiedWhereClause],
default_sized: SizedByDefault,
- f: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
// Note: This code is written to produce nice results (i.e.
// corresponding to surface Rust) for types that can occur in
@@ -978,7 +1008,9 @@ fn write_bounds_like_dyn_trait(
// We assume that the self type is ^0.0 (i.e. the
// 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)?;
+ f.end_location_link();
if let [_, params @ ..] = &*trait_ref.substitution.as_slice(Interner) {
if is_fn_trait {
if let Some(args) =
@@ -1015,7 +1047,9 @@ fn write_bounds_like_dyn_trait(
if let AliasTy::Projection(proj) = alias {
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)?;
+ f.end_location_link();
let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
if proj_arg_count > 0 {
@@ -1040,19 +1074,33 @@ fn write_bounds_like_dyn_trait(
if angle_open {
write!(f, ">")?;
}
- if matches!(default_sized, SizedByDefault::Sized { .. }) {
+ if let SizedByDefault::Sized { anchor } = default_sized {
+ let sized_trait =
+ f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
if !is_sized {
- write!(f, "{}?Sized", if first { "" } else { " + " })?;
+ if !first {
+ write!(f, " + ")?;
+ }
+ if let Some(sized_trait) = sized_trait {
+ f.start_location_link(sized_trait.into());
+ }
+ write!(f, "?Sized")?;
} else if first {
+ if let Some(sized_trait) = sized_trait {
+ f.start_location_link(sized_trait.into());
+ }
write!(f, "Sized")?;
}
+ if let Some(_) = sized_trait {
+ f.end_location_link();
+ }
}
Ok(())
}
fn fmt_trait_ref(
- tr: &TraitRef,
f: &mut HirFormatter<'_>,
+ tr: &TraitRef,
use_as: bool,
) -> Result<(), HirDisplayError> {
if f.should_truncate() {
@@ -1065,7 +1113,10 @@ fn fmt_trait_ref(
} else {
write!(f, ": ")?;
}
- write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
+ let trait_ = tr.hir_trait_id();
+ f.start_location_link(trait_.into());
+ write!(f, "{}", f.db.trait_data(trait_).name)?;
+ f.end_location_link();
if tr.substitution.len(Interner) > 1 {
write!(f, "<")?;
f.write_joined(&tr.substitution.as_slice(Interner)[1..], ", ")?;
@@ -1076,7 +1127,7 @@ fn fmt_trait_ref(
impl HirDisplay for TraitRef {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- fmt_trait_ref(self, f, false)
+ fmt_trait_ref(f, self, false)
}
}
@@ -1090,12 +1141,13 @@ impl HirDisplay for WhereClause {
WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
write!(f, "<")?;
- fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
- write!(
- f,
- ">::{} = ",
- f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
- )?;
+ fmt_trait_ref(f, &projection_ty.trait_ref(f.db), true)?;
+ 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,)?;
+ f.end_location_link();
+ write!(f, " = ")?;
ty.hir_fmt(f)?;
}
WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
@@ -1367,7 +1419,7 @@ impl HirDisplay for Path {
write!(f, "<")?;
let mut first = true;
- for arg in &generic_args.args {
+ for arg in generic_args.args.iter() {
if first {
first = false;
if generic_args.has_self_type {
@@ -1379,7 +1431,7 @@ impl HirDisplay for Path {
}
arg.hir_fmt(f)?;
}
- for binding in &generic_args.bindings {
+ for binding in generic_args.bindings.iter() {
if first {
first = false;
} else {
@@ -1393,7 +1445,7 @@ impl HirDisplay for Path {
}
None => {
write!(f, ": ")?;
- f.write_joined(&binding.bounds, " + ")?;
+ f.write_joined(binding.bounds.iter(), " + ")?;
}
}
}