diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-01-15 08:08:15 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-15 08:08:15 +0000 |
| commit | 0ed9d1c8e5dccf95eb95f8de41a7b065dd11bcf6 (patch) | |
| tree | e5bdad71c6ff53063748912e21cf74bdb21897e5 | |
| parent | a12c80ded2c84b090db1d362c5a0a07fc3538b7c (diff) | |
| parent | eed2b5cf94131dfe4c63d917dee18c66e59e4ce0 (diff) | |
| download | rust-0ed9d1c8e5dccf95eb95f8de41a7b065dd11bcf6.tar.gz rust-0ed9d1c8e5dccf95eb95f8de41a7b065dd11bcf6.zip | |
Merge pull request #18925 from Veykril/push-mtxxvpowwtrt
feat: Render type parameter projection target bounds in inlays
| -rw-r--r-- | src/tools/rust-analyzer/crates/hir-ty/src/display.rs | 49 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs | 41 |
2 files changed, 88 insertions, 2 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 a4e052a0362..3545bf76776 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -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!( diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 8a4b9590a1b..f178b4d4f07 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -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(); + //^ () +} +"#, + ); + } } |
