mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Auto merge of #17394 - Veykril:recurse-fix, r=Veykril
fix: Fix `HirDisplay` stackoverflow for parameter Self defaults Fixes https://github.com/rust-lang/rust-analyzer/issues/10932
This commit is contained in:
commit
c07076b35c
2 changed files with 48 additions and 16 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Debug},
|
fmt::{self, Debug},
|
||||||
mem::size_of,
|
mem::{self, size_of},
|
||||||
};
|
};
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
@ -460,7 +460,7 @@ impl HirDisplay for ProjectionTy {
|
||||||
let proj_params_count =
|
let proj_params_count =
|
||||||
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
|
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
|
||||||
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
|
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
|
||||||
hir_fmt_generics(f, proj_params, None)
|
hir_fmt_generics(f, proj_params, None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,6 +505,7 @@ impl HirDisplay for Const {
|
||||||
f,
|
f,
|
||||||
parameters.as_slice(Interner),
|
parameters.as_slice(Interner),
|
||||||
c.generic_def(f.db.upcast()),
|
c.generic_def(f.db.upcast()),
|
||||||
|
None,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1004,11 +1005,11 @@ impl HirDisplay for Ty {
|
||||||
let fn_params = generic_args_sans_defaults(f, Some(def.into()), fn_params);
|
let fn_params = generic_args_sans_defaults(f, Some(def.into()), fn_params);
|
||||||
|
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
hir_fmt_generic_arguments(f, parent_params)?;
|
hir_fmt_generic_arguments(f, parent_params, None)?;
|
||||||
if !parent_params.is_empty() && !fn_params.is_empty() {
|
if !parent_params.is_empty() && !fn_params.is_empty() {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
hir_fmt_generic_arguments(f, fn_params)?;
|
hir_fmt_generic_arguments(f, fn_params, None)?;
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1053,7 +1054,7 @@ impl HirDisplay for Ty {
|
||||||
|
|
||||||
let generic_def = self.as_generic_def(db);
|
let generic_def = self.as_generic_def(db);
|
||||||
|
|
||||||
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def)?;
|
hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?;
|
||||||
}
|
}
|
||||||
TyKind::AssociatedType(assoc_type_id, parameters) => {
|
TyKind::AssociatedType(assoc_type_id, parameters) => {
|
||||||
let type_alias = from_assoc_type_id(*assoc_type_id);
|
let type_alias = from_assoc_type_id(*assoc_type_id);
|
||||||
|
@ -1076,7 +1077,7 @@ impl HirDisplay for Ty {
|
||||||
f.end_location_link();
|
f.end_location_link();
|
||||||
// Note that the generic args for the associated type come before those for the
|
// Note that the generic args for the associated type come before those for the
|
||||||
// trait (including the self type).
|
// trait (including the self type).
|
||||||
hir_fmt_generics(f, parameters.as_slice(Interner), None)
|
hir_fmt_generics(f, parameters.as_slice(Interner), None, None)
|
||||||
} else {
|
} else {
|
||||||
let projection_ty = ProjectionTy {
|
let projection_ty = ProjectionTy {
|
||||||
associated_ty_id: to_assoc_type_id(type_alias),
|
associated_ty_id: to_assoc_type_id(type_alias),
|
||||||
|
@ -1178,7 +1179,7 @@ impl HirDisplay for Ty {
|
||||||
}
|
}
|
||||||
ClosureStyle::ClosureWithSubst => {
|
ClosureStyle::ClosureWithSubst => {
|
||||||
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
|
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
|
||||||
return hir_fmt_generics(f, substs.as_slice(Interner), None);
|
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -1366,6 +1367,7 @@ fn hir_fmt_generics(
|
||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
parameters: &[GenericArg],
|
parameters: &[GenericArg],
|
||||||
generic_def: Option<hir_def::GenericDefId>,
|
generic_def: Option<hir_def::GenericDefId>,
|
||||||
|
self_: Option<&Ty>,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
if parameters.is_empty() {
|
if parameters.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -1385,7 +1387,7 @@ fn hir_fmt_generics(
|
||||||
});
|
});
|
||||||
if !parameters_to_write.is_empty() && !only_err_lifetimes {
|
if !parameters_to_write.is_empty() && !only_err_lifetimes {
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
hir_fmt_generic_arguments(f, parameters_to_write)?;
|
hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,6 +1449,7 @@ fn generic_args_sans_defaults<'ga>(
|
||||||
fn hir_fmt_generic_arguments(
|
fn hir_fmt_generic_arguments(
|
||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
parameters: &[GenericArg],
|
parameters: &[GenericArg],
|
||||||
|
self_: Option<&Ty>,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
|
let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
|
||||||
|
@ -1468,11 +1471,13 @@ fn hir_fmt_generic_arguments(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !first {
|
if !mem::take(&mut first) {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
first = false;
|
match self_ {
|
||||||
generic_arg.hir_fmt(f)?;
|
self_ @ Some(_) if generic_arg.ty(Interner) == self_ => write!(f, "Self")?,
|
||||||
|
_ => generic_arg.hir_fmt(f)?,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1595,12 +1600,16 @@ fn write_bounds_like_dyn_trait(
|
||||||
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
|
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
|
||||||
f.end_location_link();
|
f.end_location_link();
|
||||||
if is_fn_trait {
|
if is_fn_trait {
|
||||||
if let [_self, params @ ..] = trait_ref.substitution.as_slice(Interner) {
|
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
|
||||||
if let Some(args) =
|
if let Some(args) =
|
||||||
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
|
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
|
||||||
{
|
{
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
hir_fmt_generic_arguments(f, args.as_slice(Interner))?;
|
hir_fmt_generic_arguments(
|
||||||
|
f,
|
||||||
|
args.as_slice(Interner),
|
||||||
|
self_.ty(Interner),
|
||||||
|
)?;
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1610,10 +1619,10 @@ fn write_bounds_like_dyn_trait(
|
||||||
Some(trait_.into()),
|
Some(trait_.into()),
|
||||||
trait_ref.substitution.as_slice(Interner),
|
trait_ref.substitution.as_slice(Interner),
|
||||||
);
|
);
|
||||||
if let [_self, params @ ..] = params {
|
if let [self_, params @ ..] = params {
|
||||||
if !params.is_empty() {
|
if !params.is_empty() {
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
hir_fmt_generic_arguments(f, params)?;
|
hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
|
||||||
// there might be assoc type bindings, so we leave the angle brackets open
|
// there might be assoc type bindings, so we leave the angle brackets open
|
||||||
angle_open = true;
|
angle_open = true;
|
||||||
}
|
}
|
||||||
|
@ -1671,6 +1680,7 @@ fn write_bounds_like_dyn_trait(
|
||||||
hir_fmt_generic_arguments(
|
hir_fmt_generic_arguments(
|
||||||
f,
|
f,
|
||||||
&proj.substitution.as_slice(Interner)[..proj_arg_count],
|
&proj.substitution.as_slice(Interner)[..proj_arg_count],
|
||||||
|
None,
|
||||||
)?;
|
)?;
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1737,8 @@ fn fmt_trait_ref(
|
||||||
f.start_location_link(trait_.into());
|
f.start_location_link(trait_.into());
|
||||||
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
|
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
|
||||||
f.end_location_link();
|
f.end_location_link();
|
||||||
hir_fmt_generics(f, &tr.substitution.as_slice(Interner)[1..], None)
|
let substs = tr.substitution.as_slice(Interner);
|
||||||
|
hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HirDisplay for TraitRef {
|
impl HirDisplay for TraitRef {
|
||||||
|
|
|
@ -709,4 +709,25 @@ fn main() {
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regression test for a stackoverflow in hir display code
|
||||||
|
#[test]
|
||||||
|
fn adjustment_hints_method_call_on_impl_trait_self() {
|
||||||
|
check_with_config(
|
||||||
|
InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
|
||||||
|
r#"
|
||||||
|
//- minicore: slice, coerce_unsized
|
||||||
|
trait T<RHS = Self> {}
|
||||||
|
|
||||||
|
fn hello(it: &&[impl T]) {
|
||||||
|
it.len();
|
||||||
|
//^^(
|
||||||
|
//^^&
|
||||||
|
//^^*
|
||||||
|
//^^*
|
||||||
|
//^^)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue