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.rs82
1 files changed, 67 insertions, 15 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 20964f5acb..8740ae6797 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -938,18 +938,32 @@ impl HirDisplay for Ty {
f.end_location_link();
if parameters.len(Interner) > 0 {
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;
+ let (
+ parent_params,
+ self_param,
+ type_params,
+ const_params,
+ _impl_trait_params,
+ lifetime_params,
+ ) = generics.provenance_split();
+ let total_len =
+ parent_params + self_param + type_params + const_params + lifetime_params;
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
if total_len > 0 {
- // `parameters` are in the order of fn's params (including impl traits),
+ // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
// parent's params (those from enclosing impl or trait, if any).
let parameters = parameters.as_slice(Interner);
let fn_params_len = self_param + type_params + const_params;
+ // This will give slice till last type or const
let fn_params = parameters.get(..fn_params_len);
+ let fn_lt_params =
+ parameters.get(fn_params_len..(fn_params_len + lifetime_params));
let parent_params = parameters.get(parameters.len() - parent_params..);
- let params = parent_params.into_iter().chain(fn_params).flatten();
+ let params = parent_params
+ .into_iter()
+ .chain(fn_lt_params)
+ .chain(fn_params)
+ .flatten();
write!(f, "<")?;
f.write_joined(params, ", ")?;
write!(f, ">")?;
@@ -1063,6 +1077,20 @@ impl HirDisplay for Ty {
)?;
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
}
+ ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+ let datas =
+ db.type_alias_impl_traits(alias).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 = alias.krate(db.upcast());
+ write_bounds_like_dyn_trait_with_prefix(
+ f,
+ "impl",
+ bounds.skip_binders(),
+ SizedByDefault::Sized { anchor: krate },
+ )?;
+ }
ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
let future_trait = db
.lang_item(body.module(db.upcast()).krate(), LangItem::Future)
@@ -1228,6 +1256,20 @@ impl HirDisplay for Ty {
SizedByDefault::Sized { anchor: krate },
)?;
}
+ ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+ let datas =
+ db.type_alias_impl_traits(alias).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 = alias.krate(db.upcast());
+ write_bounds_like_dyn_trait_with_prefix(
+ f,
+ "impl",
+ bounds.skip_binders(),
+ SizedByDefault::Sized { anchor: krate },
+ )?;
+ }
ImplTraitId::AsyncBlockTypeImplTrait(..) => {
write!(f, "{{async block}}")?;
}
@@ -1280,8 +1322,17 @@ fn hir_fmt_generics(
generic_def: Option<hir_def::GenericDefId>,
) -> Result<(), HirDisplayError> {
let db = f.db;
- let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
- if parameters.len(Interner) + lifetime_args_count > 0 {
+ if parameters.len(Interner) > 0 {
+ use std::cmp::Ordering;
+ let param_compare =
+ |a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) {
+ (crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => {
+ Ordering::Equal
+ }
+ (crate::GenericArgData::Lifetime(_), _) => Ordering::Less,
+ (_, crate::GenericArgData::Lifetime(_)) => Ordering::Less,
+ (_, _) => Ordering::Equal,
+ };
let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
match generic_def
.map(|generic_def_id| db.generic_defaults(generic_def_id))
@@ -1307,6 +1358,11 @@ fn hir_fmt_generics(
return true;
}
}
+ if parameter.lifetime(Interner).map(|it| it.data(Interner))
+ == Some(&crate::LifetimeData::Static)
+ {
+ return true;
+ }
let default_parameter = match default_parameters.get(i) {
Some(it) => it,
None => return true,
@@ -1327,16 +1383,12 @@ fn hir_fmt_generics(
} else {
parameters.as_slice(Interner)
};
- if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
+ //FIXME: Should handle the ordering of lifetimes when creating substitutions
+ let mut parameters_to_write = parameters_to_write.to_vec();
+ parameters_to_write.sort_by(param_compare);
+ if !parameters_to_write.is_empty() {
write!(f, "<")?;
let mut first = true;
- for _ in 0..lifetime_args_count {
- if !first {
- write!(f, ", ")?;
- }
- first = false;
- write!(f, "'_")?;
- }
for generic_arg in parameters_to_write {
if !first {
write!(f, ", ")?;