mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
Display generic arguments for associated types
This commit is contained in:
parent
1fe10bff1d
commit
4dd694371a
3 changed files with 78 additions and 17 deletions
|
@ -289,16 +289,18 @@ impl HirDisplay for ProjectionTy {
|
||||||
return write!(f, "{}", TYPE_HINT_TRUNCATION);
|
return write!(f, "{}", TYPE_HINT_TRUNCATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_ = f.db.trait_data(self.trait_(f.db));
|
let trait_ref = self.trait_ref(f.db);
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
self.self_type_parameter(f.db).hir_fmt(f)?;
|
fmt_trait_ref(&trait_ref, f, true)?;
|
||||||
write!(f, " as {}", trait_.name)?;
|
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
|
||||||
if self.substitution.len(Interner) > 1 {
|
let proj_params_count =
|
||||||
|
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
|
||||||
|
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
|
||||||
|
if !proj_params.is_empty() {
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
f.write_joined(&self.substitution.as_slice(Interner)[1..], ", ")?;
|
f.write_joined(proj_params, ", ")?;
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -641,9 +643,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)
|
// 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() {
|
if f.display_target.is_test() {
|
||||||
write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
|
write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
|
||||||
|
// 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?
|
||||||
if parameters.len(Interner) > 0 {
|
if parameters.len(Interner) > 0 {
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
f.write_joined(&*parameters.as_slice(Interner), ", ")?;
|
f.write_joined(parameters.as_slice(Interner), ", ")?;
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -972,9 +977,20 @@ fn write_bounds_like_dyn_trait(
|
||||||
angle_open = true;
|
angle_open = true;
|
||||||
}
|
}
|
||||||
if let AliasTy::Projection(proj) = alias {
|
if let AliasTy::Projection(proj) = alias {
|
||||||
let type_alias =
|
let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
|
||||||
f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id));
|
let type_alias = f.db.type_alias_data(assoc_ty_id);
|
||||||
write!(f, "{} = ", type_alias.name)?;
|
write!(f, "{}", type_alias.name)?;
|
||||||
|
|
||||||
|
let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
|
||||||
|
if proj_arg_count > 0 {
|
||||||
|
write!(f, "<")?;
|
||||||
|
f.write_joined(
|
||||||
|
&proj.substitution.as_slice(Interner)[..proj_arg_count],
|
||||||
|
", ",
|
||||||
|
)?;
|
||||||
|
write!(f, ">")?;
|
||||||
|
}
|
||||||
|
write!(f, " = ")?;
|
||||||
}
|
}
|
||||||
ty.hir_fmt(f)?;
|
ty.hir_fmt(f)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,3 +196,34 @@ fn test(
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn projection_type_correct_arguments_order() {
|
||||||
|
check_types_source_code(
|
||||||
|
r#"
|
||||||
|
trait Foo<T> {
|
||||||
|
type Assoc<U>;
|
||||||
|
}
|
||||||
|
fn f<T: Foo<i32>>(a: T::Assoc<usize>) {
|
||||||
|
a;
|
||||||
|
//^ <T as Foo<i32>>::Assoc<usize>
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_associated_type_binding_in_impl_trait() {
|
||||||
|
check_types_source_code(
|
||||||
|
r#"
|
||||||
|
//- minicore: sized
|
||||||
|
trait Foo<T> {
|
||||||
|
type Assoc<U>;
|
||||||
|
}
|
||||||
|
fn f(a: impl Foo<i8, Assoc<i16> = i32>) {
|
||||||
|
a;
|
||||||
|
//^ impl Foo<i8, Assoc<i16> = i32>
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk,
|
chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk,
|
||||||
CallableDefId, Interner,
|
CallableDefId, Interner, ProjectionTyExt,
|
||||||
};
|
};
|
||||||
use hir_def::{AdtId, ItemContainerId, Lookup, TypeAliasId};
|
use hir_def::{AdtId, ItemContainerId, Lookup, TypeAliasId};
|
||||||
|
|
||||||
|
@ -63,17 +63,31 @@ impl DebugContext<'_> {
|
||||||
ItemContainerId::TraitId(t) => t,
|
ItemContainerId::TraitId(t) => t,
|
||||||
_ => panic!("associated type not in trait"),
|
_ => panic!("associated type not in trait"),
|
||||||
};
|
};
|
||||||
let trait_data = self.0.trait_data(trait_);
|
let trait_name = &self.0.trait_data(trait_).name;
|
||||||
let params = projection_ty.substitution.as_slice(Interner);
|
let trait_ref = projection_ty.trait_ref(self.0);
|
||||||
write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?;
|
let trait_params = trait_ref.substitution.as_slice(Interner);
|
||||||
if params.len() > 1 {
|
let self_ty = trait_ref.self_type_parameter(Interner);
|
||||||
|
write!(fmt, "<{:?} as {}", self_ty, trait_name)?;
|
||||||
|
if trait_params.len() > 1 {
|
||||||
write!(
|
write!(
|
||||||
fmt,
|
fmt,
|
||||||
"<{}>",
|
"<{}>",
|
||||||
¶ms[1..].iter().format_with(", ", |x, f| f(&format_args!("{:?}", x))),
|
trait_params[1..].iter().format_with(", ", |x, f| f(&format_args!("{:?}", x))),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
write!(fmt, ">::{}", type_alias_data.name)
|
write!(fmt, ">::{}", type_alias_data.name)?;
|
||||||
|
|
||||||
|
let proj_params_count = projection_ty.substitution.len(Interner) - trait_params.len();
|
||||||
|
let proj_params = &projection_ty.substitution.as_slice(Interner)[..proj_params_count];
|
||||||
|
if !proj_params.is_empty() {
|
||||||
|
write!(
|
||||||
|
fmt,
|
||||||
|
"<{}>",
|
||||||
|
proj_params.iter().format_with(", ", |x, f| f(&format_args!("{:?}", x))),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn debug_fn_def_id(
|
pub(crate) fn debug_fn_def_id(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue