Skip to content

Commit 36caa43

Browse files
committed
fix: Fix HirDisplay stackoverflow for parameter Self defaults
1 parent 0ef2213 commit 36caa43

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/display.rs

+27-16
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use std::{
66
fmt::{self, Debug},
7-
mem::size_of,
7+
mem::{self, size_of},
88
};
99

1010
use base_db::CrateId;
@@ -423,7 +423,7 @@ impl HirDisplay for ProjectionTy {
423423
let proj_params_count =
424424
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
425425
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
426-
hir_fmt_generics(f, proj_params, None)
426+
hir_fmt_generics(f, proj_params, None, None)
427427
}
428428
}
429429

@@ -468,6 +468,7 @@ impl HirDisplay for Const {
468468
f,
469469
parameters.as_slice(Interner),
470470
c.generic_def(f.db.upcast()),
471+
None,
471472
)?;
472473
Ok(())
473474
}
@@ -967,11 +968,11 @@ impl HirDisplay for Ty {
967968
let fn_params = generic_args_sans_defaults(f, Some(def.into()), fn_params);
968969

969970
write!(f, "<")?;
970-
hir_fmt_generic_arguments(f, parent_params)?;
971+
hir_fmt_generic_arguments(f, parent_params, None)?;
971972
if !parent_params.is_empty() && !fn_params.is_empty() {
972973
write!(f, ", ")?;
973974
}
974-
hir_fmt_generic_arguments(f, fn_params)?;
975+
hir_fmt_generic_arguments(f, fn_params, None)?;
975976
write!(f, ">")?;
976977
}
977978
}
@@ -1016,7 +1017,7 @@ impl HirDisplay for Ty {
10161017

10171018
let generic_def = self.as_generic_def(db);
10181019

1019-
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def)?;
1020+
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?;
10201021
}
10211022
TyKind::AssociatedType(assoc_type_id, parameters) => {
10221023
let type_alias = from_assoc_type_id(*assoc_type_id);
@@ -1039,7 +1040,7 @@ impl HirDisplay for Ty {
10391040
f.end_location_link();
10401041
// Note that the generic args for the associated type come before those for the
10411042
// trait (including the self type).
1042-
hir_fmt_generics(f, parameters.as_slice(Interner), None)
1043+
hir_fmt_generics(f, parameters.as_slice(Interner), None, None)
10431044
} else {
10441045
let projection_ty = ProjectionTy {
10451046
associated_ty_id: to_assoc_type_id(type_alias),
@@ -1141,7 +1142,7 @@ impl HirDisplay for Ty {
11411142
}
11421143
ClosureStyle::ClosureWithSubst => {
11431144
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
1144-
return hir_fmt_generics(f, substs.as_slice(Interner), None);
1145+
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
11451146
}
11461147
_ => (),
11471148
}
@@ -1329,6 +1330,7 @@ fn hir_fmt_generics(
13291330
f: &mut HirFormatter<'_>,
13301331
parameters: &[GenericArg],
13311332
generic_def: Option<hir_def::GenericDefId>,
1333+
self_: Option<&Ty>,
13321334
) -> Result<(), HirDisplayError> {
13331335
if parameters.is_empty() {
13341336
return Ok(());
@@ -1348,7 +1350,7 @@ fn hir_fmt_generics(
13481350
});
13491351
if !parameters_to_write.is_empty() && !only_err_lifetimes {
13501352
write!(f, "<")?;
1351-
hir_fmt_generic_arguments(f, parameters_to_write)?;
1353+
hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
13521354
write!(f, ">")?;
13531355
}
13541356

@@ -1410,6 +1412,7 @@ fn generic_args_sans_defaults<'ga>(
14101412
fn hir_fmt_generic_arguments(
14111413
f: &mut HirFormatter<'_>,
14121414
parameters: &[GenericArg],
1415+
self_: Option<&Ty>,
14131416
) -> Result<(), HirDisplayError> {
14141417
let mut first = true;
14151418
let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
@@ -1431,11 +1434,13 @@ fn hir_fmt_generic_arguments(
14311434
continue;
14321435
}
14331436

1434-
if !first {
1437+
if !mem::take(&mut first) {
14351438
write!(f, ", ")?;
14361439
}
1437-
first = false;
1438-
generic_arg.hir_fmt(f)?;
1440+
match self_ {
1441+
self_ @ Some(_) if generic_arg.ty(Interner) == self_ => write!(f, "Self")?,
1442+
_ => generic_arg.hir_fmt(f)?,
1443+
}
14391444
}
14401445
Ok(())
14411446
}
@@ -1558,12 +1563,16 @@ fn write_bounds_like_dyn_trait(
15581563
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
15591564
f.end_location_link();
15601565
if is_fn_trait {
1561-
if let [_self, params @ ..] = trait_ref.substitution.as_slice(Interner) {
1566+
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
15621567
if let Some(args) =
15631568
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
15641569
{
15651570
write!(f, "(")?;
1566-
hir_fmt_generic_arguments(f, args.as_slice(Interner))?;
1571+
hir_fmt_generic_arguments(
1572+
f,
1573+
args.as_slice(Interner),
1574+
self_.ty(Interner),
1575+
)?;
15671576
write!(f, ")")?;
15681577
}
15691578
}
@@ -1573,10 +1582,10 @@ fn write_bounds_like_dyn_trait(
15731582
Some(trait_.into()),
15741583
trait_ref.substitution.as_slice(Interner),
15751584
);
1576-
if let [_self, params @ ..] = params {
1585+
if let [self_, params @ ..] = params {
15771586
if !params.is_empty() {
15781587
write!(f, "<")?;
1579-
hir_fmt_generic_arguments(f, params)?;
1588+
hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
15801589
// there might be assoc type bindings, so we leave the angle brackets open
15811590
angle_open = true;
15821591
}
@@ -1634,6 +1643,7 @@ fn write_bounds_like_dyn_trait(
16341643
hir_fmt_generic_arguments(
16351644
f,
16361645
&proj.substitution.as_slice(Interner)[..proj_arg_count],
1646+
None,
16371647
)?;
16381648
write!(f, ">")?;
16391649
}
@@ -1690,7 +1700,8 @@ fn fmt_trait_ref(
16901700
f.start_location_link(trait_.into());
16911701
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
16921702
f.end_location_link();
1693-
hir_fmt_generics(f, &tr.substitution.as_slice(Interner)[1..], None)
1703+
let substs = tr.substitution.as_slice(Interner);
1704+
hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
16941705
}
16951706

16961707
impl HirDisplay for TraitRef {

src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs

+21
Original file line numberDiff line numberDiff line change
@@ -709,4 +709,25 @@ fn main() {
709709
"#,
710710
)
711711
}
712+
713+
// regression test for a stackoverflow in hir display code
714+
#[test]
715+
fn adjustment_hints_method_call_on_impl_trait_self() {
716+
check_with_config(
717+
InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
718+
r#"
719+
//- minicore: slice, coerce_unsized
720+
trait T<RHS = Self> {}
721+
722+
fn hello(it: &&[impl T]) {
723+
it.len();
724+
//^^(
725+
//^^&
726+
//^^*
727+
//^^*
728+
//^^)
729+
}
730+
"#,
731+
);
732+
}
712733
}

0 commit comments

Comments
 (0)