Skip to content

Commit f0f7204

Browse files
committed
Fix Param::as_local treating closures wrong
1 parent 54d1d31 commit f0f7204

File tree

4 files changed

+67
-53
lines changed

4 files changed

+67
-53
lines changed

src/tools/rust-analyzer/crates/hir/src/lib.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use hir_def::{
4545
body::BodyDiagnostic,
4646
data::{adt::VariantData, TraitFlags},
4747
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
48-
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
48+
hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
4949
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
5050
lang_item::LangItemTarget,
5151
layout::{self, ReprOptions, TargetDataLayout},
@@ -2470,20 +2470,31 @@ impl Param {
24702470
}
24712471

24722472
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
2473-
let parent = match self.func {
2474-
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
2475-
Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
2476-
_ => return None,
2477-
};
2478-
let body = db.body(parent);
2479-
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
2480-
Some(Local { parent, binding_id: self_param })
2481-
} else if let Pat::Bind { id, .. } =
2482-
&body[body.params[self.idx - body.self_param.is_some() as usize]]
2483-
{
2484-
Some(Local { parent, binding_id: *id })
2485-
} else {
2486-
None
2473+
match self.func {
2474+
Callee::Def(CallableDefId::FunctionId(it)) => {
2475+
let parent = DefWithBodyId::FunctionId(it);
2476+
let body = db.body(parent);
2477+
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
2478+
Some(Local { parent, binding_id: self_param })
2479+
} else if let Pat::Bind { id, .. } =
2480+
&body[body.params[self.idx - body.self_param.is_some() as usize]]
2481+
{
2482+
Some(Local { parent, binding_id: *id })
2483+
} else {
2484+
None
2485+
}
2486+
}
2487+
Callee::Closure(closure, _) => {
2488+
let c = db.lookup_intern_closure(closure.into());
2489+
let body = db.body(c.0);
2490+
if let Expr::Closure { args, .. } = &body[c.1] {
2491+
if let Pat::Bind { id, .. } = &body[args[self.idx]] {
2492+
return Some(Local { parent: c.0, binding_id: *id });
2493+
}
2494+
}
2495+
None
2496+
}
2497+
_ => None,
24872498
}
24882499
}
24892500

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ fn hints(
209209
) {
210210
closing_brace::hints(hints, sema, config, file_id, node.clone());
211211
if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
212-
generic_param::hints(hints, sema, config, any_has_generic_args);
212+
generic_param::hints(hints, famous_defs, config, any_has_generic_args);
213213
}
214214

215215
match_ast! {

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
//! Implementation of inlay hints for generic parameters.
2-
use ide_db::{active_parameter::generic_def_for_node, RootDatabase};
2+
use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs};
33
use syntax::{
44
ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName},
55
AstNode,
66
};
77

8-
use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind};
8+
use crate::{
9+
inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
10+
};
911

10-
use super::param_name::{is_argument_similar_to_param_name, render_label};
12+
use super::param_name::is_argument_similar_to_param_name;
1113

1214
pub(crate) fn hints(
1315
acc: &mut Vec<InlayHint>,
14-
sema: &hir::Semantics<'_, RootDatabase>,
16+
FamousDefs(sema, krate): &FamousDefs<'_, '_>,
1517
config: &InlayHintsConfig,
1618
node: AnyHasGenericArgs,
1719
) -> Option<()> {
@@ -45,12 +47,11 @@ pub(crate) fn hints(
4547
return None;
4648
}
4749

48-
let name = param.name(sema.db);
49-
let param_name = name.as_str();
50+
let param_name = param.name(sema.db);
5051

5152
let should_hide = {
5253
let argument = get_string_representation(&arg)?;
53-
is_argument_similar_to_param_name(&argument, param_name)
54+
is_argument_similar_to_param_name(&argument, param_name.as_str())
5455
};
5556

5657
if should_hide {
@@ -64,25 +65,30 @@ pub(crate) fn hints(
6465
if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) {
6566
return None;
6667
}
67-
sema.source(it.merge())?.value.syntax().clone()
68+
sema.source(it.merge()).map(|it| it.value.syntax().clone())
6869
}
6970
hir::GenericParam::ConstParam(it) => {
7071
if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) {
7172
return None;
7273
}
7374
let syntax = sema.source(it.merge())?.value.syntax().clone();
7475
let const_param = ast::ConstParam::cast(syntax)?;
75-
const_param.name()?.syntax().clone()
76+
const_param.name().map(|it| it.syntax().clone())
7677
}
7778
hir::GenericParam::LifetimeParam(it) => {
7879
if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) {
7980
return None;
8081
}
81-
sema.source(it)?.value.syntax().clone()
82+
sema.source(it).map(|it| it.value.syntax().clone())
8283
}
8384
};
84-
let linked_location = sema.original_range_opt(&source_syntax);
85-
let label = render_label(param_name, config, linked_location);
85+
let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it));
86+
let colon = if config.render_colons { ":" } else { "" };
87+
let label = InlayHintLabel::simple(
88+
format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
89+
None,
90+
linked_location.map(Into::into),
91+
);
8692

8793
Some(InlayHint {
8894
range,

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

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! fn max(x: i32, y: i32) -> i32 { x + y }
44
//! _ = max(/*x*/4, /*y*/4);
55
//! ```
6-
use std::fmt::Display;
76
87
use either::Either;
98
use hir::{Callable, Semantics};
@@ -20,7 +19,7 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla
2019

2120
pub(super) fn hints(
2221
acc: &mut Vec<InlayHint>,
23-
FamousDefs(sema, _): &FamousDefs<'_, '_>,
22+
FamousDefs(sema, krate): &FamousDefs<'_, '_>,
2423
config: &InlayHintsConfig,
2524
_file_id: EditionedFileId,
2625
expr: ast::Expr,
@@ -37,23 +36,31 @@ pub(super) fn hints(
3736
.filter_map(|(p, arg)| {
3837
// Only annotate hints for expressions that exist in the original file
3938
let range = sema.original_range_opt(arg.syntax())?;
40-
let source = sema.source(p)?;
41-
let (param_name, name_syntax) = match source.value.as_ref() {
42-
Either::Left(pat) => (pat.name()?, pat.name()),
43-
Either::Right(param) => match param.pat()? {
44-
ast::Pat::IdentPat(it) => (it.name()?, it.name()),
45-
_ => return None,
46-
},
47-
};
48-
Some((name_syntax, param_name, arg, range))
39+
let param_name = p.name(sema.db)?;
40+
Some((p, param_name, arg, range))
4941
})
5042
.filter(|(_, param_name, arg, _)| {
51-
!should_hide_param_name_hint(sema, &callable, &param_name.text(), arg)
43+
!should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg)
5244
})
5345
.map(|(param, param_name, _, hir::FileRange { range, .. })| {
54-
let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
55-
56-
let label = render_label(&param_name, config, linked_location);
46+
let linked_location = (|| {
47+
let source = sema.source(param)?;
48+
let name_syntax = match source.value.as_ref() {
49+
Either::Left(pat) => pat.name(),
50+
Either::Right(param) => match param.pat()? {
51+
ast::Pat::IdentPat(it) => it.name(),
52+
_ => None,
53+
},
54+
}?;
55+
sema.original_range_opt(name_syntax.syntax())
56+
})();
57+
58+
let colon = if config.render_colons { ":" } else { "" };
59+
let label = InlayHintLabel::simple(
60+
format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
61+
None,
62+
linked_location.map(Into::into),
63+
);
5764
InlayHint {
5865
range,
5966
kind: InlayKind::Parameter,
@@ -70,16 +77,6 @@ pub(super) fn hints(
7077
Some(())
7178
}
7279

73-
pub(super) fn render_label(
74-
param_name: impl Display,
75-
config: &InlayHintsConfig,
76-
linked_location: Option<hir::FileRange>,
77-
) -> InlayHintLabel {
78-
let colon = if config.render_colons { ":" } else { "" };
79-
80-
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location.map(Into::into))
81-
}
82-
8380
fn get_callable(
8481
sema: &Semantics<'_, RootDatabase>,
8582
expr: &ast::Expr,

0 commit comments

Comments
 (0)