Skip to content

Commit

Permalink
Merge pull request #18925 from Veykril/push-mtxxvpowwtrt
Browse files Browse the repository at this point in the history
feat: Render type parameter projection target bounds in inlays
  • Loading branch information
Veykril authored Jan 15, 2025
2 parents d82e1a2 + 5530167 commit 9384cee
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 2 deletions.
49 changes: 47 additions & 2 deletions crates/hir-ty/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,55 @@ impl HirDisplay for ProjectionTy {
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
}

let trait_ref = self.trait_ref(f.db);
let self_ty = trait_ref.self_type_parameter(Interner);

// if we are projection on a type parameter, check if the projection target has bounds
// itself, if so, we render them directly as `impl Bound` instead of the less useful
// `<Param as Trait>::Assoc`
if !f.display_target.is_source_code() {
if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
let db = f.db;
let id = from_placeholder_idx(db, *idx);
let generics = generics(db.upcast(), id.parent);

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) => {
match tr.self_type_parameter(Interner).kind(Interner) {
TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
_ => false,
}
}
WhereClause::TypeOutlives(t) => match t.ty.kind(Interner) {
TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
_ => false,
},
// We shouldn't be here if these exist
WhereClause::AliasEq(_) => false,
WhereClause::LifetimeOutlives(_) => false,
})
.collect::<Vec<_>>();
if !bounds.is_empty() {
return write_bounds_like_dyn_trait_with_prefix(
f,
"impl",
Either::Left(
&TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner),
),
&bounds,
SizedByDefault::NotSized,
);
};
}
}

write!(f, "<")?;
trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
self_ty.hir_fmt(f)?;
write!(f, " as ")?;
trait_ref.hir_fmt(f)?;
write!(
Expand Down
41 changes: 41 additions & 0 deletions crates/ide/src/inlay_hints/bind_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,4 +1164,45 @@ fn main() {
}"#,
);
}

#[test]
fn collapses_nested_impl_projections() {
check_types(
r#"
//- minicore: sized
trait T {
type Assoc;
fn f(self) -> Self::Assoc;
}
trait T2 {}
trait T3<T> {}
fn f(it: impl T<Assoc: T2>) {
let l = it.f();
// ^ impl T2
}
fn f2<G: T<Assoc: T2 + 'static>>(it: G) {
let l = it.f();
//^ impl T2 + 'static
}
fn f3<G: T>(it: G) where <G as T>::Assoc: T2 {
let l = it.f();
//^ impl T2
}
fn f4<G: T<Assoc: T2 + T3<()>>>(it: G) {
let l = it.f();
//^ impl T2 + T3<()>
}
fn f5<G: T<Assoc = ()>>(it: G) {
let l = it.f();
//^ ()
}
"#,
);
}
}

0 comments on commit 9384cee

Please sign in to comment.