Skip to content

Commit 5e1ab70

Browse files
committed
Auto merge of #17394 - Veykril:recurse-fix, r=Veykril
fix: Fix `HirDisplay` stackoverflow for parameter Self defaults Fixes rust-lang/rust-analyzer#10932
2 parents 21e9022 + 36caa43 commit 5e1ab70

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;
@@ -460,7 +460,7 @@ impl HirDisplay for ProjectionTy {
460460
let proj_params_count =
461461
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
462462
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
463-
hir_fmt_generics(f, proj_params, None)
463+
hir_fmt_generics(f, proj_params, None, None)
464464
}
465465
}
466466

@@ -505,6 +505,7 @@ impl HirDisplay for Const {
505505
f,
506506
parameters.as_slice(Interner),
507507
c.generic_def(f.db.upcast()),
508+
None,
508509
)?;
509510
Ok(())
510511
}
@@ -1004,11 +1005,11 @@ impl HirDisplay for Ty {
10041005
let fn_params = generic_args_sans_defaults(f, Some(def.into()), fn_params);
10051006

10061007
write!(f, "<")?;
1007-
hir_fmt_generic_arguments(f, parent_params)?;
1008+
hir_fmt_generic_arguments(f, parent_params, None)?;
10081009
if !parent_params.is_empty() && !fn_params.is_empty() {
10091010
write!(f, ", ")?;
10101011
}
1011-
hir_fmt_generic_arguments(f, fn_params)?;
1012+
hir_fmt_generic_arguments(f, fn_params, None)?;
10121013
write!(f, ">")?;
10131014
}
10141015
}
@@ -1053,7 +1054,7 @@ impl HirDisplay for Ty {
10531054

10541055
let generic_def = self.as_generic_def(db);
10551056

1056-
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def)?;
1057+
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?;
10571058
}
10581059
TyKind::AssociatedType(assoc_type_id, parameters) => {
10591060
let type_alias = from_assoc_type_id(*assoc_type_id);
@@ -1076,7 +1077,7 @@ impl HirDisplay for Ty {
10761077
f.end_location_link();
10771078
// Note that the generic args for the associated type come before those for the
10781079
// trait (including the self type).
1079-
hir_fmt_generics(f, parameters.as_slice(Interner), None)
1080+
hir_fmt_generics(f, parameters.as_slice(Interner), None, None)
10801081
} else {
10811082
let projection_ty = ProjectionTy {
10821083
associated_ty_id: to_assoc_type_id(type_alias),
@@ -1178,7 +1179,7 @@ impl HirDisplay for Ty {
11781179
}
11791180
ClosureStyle::ClosureWithSubst => {
11801181
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
1181-
return hir_fmt_generics(f, substs.as_slice(Interner), None);
1182+
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
11821183
}
11831184
_ => (),
11841185
}
@@ -1366,6 +1367,7 @@ fn hir_fmt_generics(
13661367
f: &mut HirFormatter<'_>,
13671368
parameters: &[GenericArg],
13681369
generic_def: Option<hir_def::GenericDefId>,
1370+
self_: Option<&Ty>,
13691371
) -> Result<(), HirDisplayError> {
13701372
if parameters.is_empty() {
13711373
return Ok(());
@@ -1385,7 +1387,7 @@ fn hir_fmt_generics(
13851387
});
13861388
if !parameters_to_write.is_empty() && !only_err_lifetimes {
13871389
write!(f, "<")?;
1388-
hir_fmt_generic_arguments(f, parameters_to_write)?;
1390+
hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
13891391
write!(f, ">")?;
13901392
}
13911393

@@ -1447,6 +1449,7 @@ fn generic_args_sans_defaults<'ga>(
14471449
fn hir_fmt_generic_arguments(
14481450
f: &mut HirFormatter<'_>,
14491451
parameters: &[GenericArg],
1452+
self_: Option<&Ty>,
14501453
) -> Result<(), HirDisplayError> {
14511454
let mut first = true;
14521455
let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
@@ -1468,11 +1471,13 @@ fn hir_fmt_generic_arguments(
14681471
continue;
14691472
}
14701473

1471-
if !first {
1474+
if !mem::take(&mut first) {
14721475
write!(f, ", ")?;
14731476
}
1474-
first = false;
1475-
generic_arg.hir_fmt(f)?;
1477+
match self_ {
1478+
self_ @ Some(_) if generic_arg.ty(Interner) == self_ => write!(f, "Self")?,
1479+
_ => generic_arg.hir_fmt(f)?,
1480+
}
14761481
}
14771482
Ok(())
14781483
}
@@ -1595,12 +1600,16 @@ fn write_bounds_like_dyn_trait(
15951600
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
15961601
f.end_location_link();
15971602
if is_fn_trait {
1598-
if let [_self, params @ ..] = trait_ref.substitution.as_slice(Interner) {
1603+
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
15991604
if let Some(args) =
16001605
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
16011606
{
16021607
write!(f, "(")?;
1603-
hir_fmt_generic_arguments(f, args.as_slice(Interner))?;
1608+
hir_fmt_generic_arguments(
1609+
f,
1610+
args.as_slice(Interner),
1611+
self_.ty(Interner),
1612+
)?;
16041613
write!(f, ")")?;
16051614
}
16061615
}
@@ -1610,10 +1619,10 @@ fn write_bounds_like_dyn_trait(
16101619
Some(trait_.into()),
16111620
trait_ref.substitution.as_slice(Interner),
16121621
);
1613-
if let [_self, params @ ..] = params {
1622+
if let [self_, params @ ..] = params {
16141623
if !params.is_empty() {
16151624
write!(f, "<")?;
1616-
hir_fmt_generic_arguments(f, params)?;
1625+
hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
16171626
// there might be assoc type bindings, so we leave the angle brackets open
16181627
angle_open = true;
16191628
}
@@ -1671,6 +1680,7 @@ fn write_bounds_like_dyn_trait(
16711680
hir_fmt_generic_arguments(
16721681
f,
16731682
&proj.substitution.as_slice(Interner)[..proj_arg_count],
1683+
None,
16741684
)?;
16751685
write!(f, ">")?;
16761686
}
@@ -1727,7 +1737,8 @@ fn fmt_trait_ref(
17271737
f.start_location_link(trait_.into());
17281738
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
17291739
f.end_location_link();
1730-
hir_fmt_generics(f, &tr.substitution.as_slice(Interner)[1..], None)
1740+
let substs = tr.substitution.as_slice(Interner);
1741+
hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
17311742
}
17321743

17331744
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)