Skip to content

Commit 7b01343

Browse files
committed
Auto merge of rust-lang#18012 - Veykril:inlay-hints-lt, r=Veykril
fix: Fix lifetime elision inlay hints breaking for ranged requests
2 parents 1850ce3 + 5acbc4f commit 7b01343

File tree

2 files changed

+59
-57
lines changed

2 files changed

+59
-57
lines changed

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

Lines changed: 58 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId};
1515
use stdx::never;
1616
use syntax::{
1717
ast::{self, AstNode, HasGenericParams},
18-
format_smolstr, match_ast, NodeOrToken, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
18+
format_smolstr, match_ast, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
1919
};
2020
use text_edit::TextEdit;
2121

@@ -95,26 +95,27 @@ pub(crate) fn inlay_hints(
9595
let famous_defs = FamousDefs(&sema, scope.krate());
9696

9797
let ctx = &mut InlayHintCtx::default();
98-
let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node);
99-
match range_limit {
100-
// FIXME: This can miss some hints that require the parent of the range to calculate
101-
Some(range) => match file.covering_element(range) {
102-
NodeOrToken::Token(_) => return acc,
103-
NodeOrToken::Node(n) => n
104-
.preorder()
105-
.filter(|event| matches!(event, WalkEvent::Enter(node) if range.intersect(node.text_range()).is_some()))
106-
.for_each(hints),
107-
},
108-
None => file.preorder().for_each(hints),
98+
let mut hints = |event| {
99+
if let Some(node) = handle_event(ctx, event) {
100+
hints(&mut acc, ctx, &famous_defs, config, file_id, node);
101+
}
109102
};
110-
103+
let mut preorder = file.preorder();
104+
while let Some(event) = preorder.next() {
105+
// FIXME: This can miss some hints that require the parent of the range to calculate
106+
if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none())
107+
{
108+
preorder.skip_subtree();
109+
continue;
110+
}
111+
hints(event);
112+
}
111113
acc
112114
}
113115

114116
#[derive(Default)]
115117
struct InlayHintCtx {
116118
lifetime_stacks: Vec<Vec<SmolStr>>,
117-
is_param_list: bool,
118119
}
119120

120121
pub(crate) fn inlay_hints_resolve(
@@ -138,20 +139,52 @@ pub(crate) fn inlay_hints_resolve(
138139
let mut acc = Vec::new();
139140

140141
let ctx = &mut InlayHintCtx::default();
141-
let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node);
142-
143-
let mut res = file.clone();
144-
let res = loop {
145-
res = match res.child_or_token_at_range(resolve_range) {
146-
Some(NodeOrToken::Node(n)) if n.text_range() == resolve_range => break n,
147-
Some(NodeOrToken::Node(n)) => n,
148-
_ => break res,
149-
};
142+
let mut hints = |event| {
143+
if let Some(node) = handle_event(ctx, event) {
144+
hints(&mut acc, ctx, &famous_defs, config, file_id, node);
145+
}
150146
};
151-
res.preorder().for_each(hints);
147+
148+
let mut preorder = file.preorder();
149+
while let Some(event) = preorder.next() {
150+
// FIXME: This can miss some hints that require the parent of the range to calculate
151+
if matches!(&event, WalkEvent::Enter(node) if resolve_range.intersect(node.text_range()).is_none())
152+
{
153+
preorder.skip_subtree();
154+
continue;
155+
}
156+
hints(event);
157+
}
152158
acc.into_iter().find(|hint| hasher(hint) == hash)
153159
}
154160

161+
fn handle_event(ctx: &mut InlayHintCtx, node: WalkEvent<SyntaxNode>) -> Option<SyntaxNode> {
162+
match node {
163+
WalkEvent::Enter(node) => {
164+
if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) {
165+
let params = node
166+
.generic_param_list()
167+
.map(|it| {
168+
it.lifetime_params()
169+
.filter_map(|it| {
170+
it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..]))
171+
})
172+
.collect()
173+
})
174+
.unwrap_or_default();
175+
ctx.lifetime_stacks.push(params);
176+
}
177+
Some(node)
178+
}
179+
WalkEvent::Leave(n) => {
180+
if ast::AnyHasGenericParams::can_cast(n.kind()) {
181+
ctx.lifetime_stacks.pop();
182+
}
183+
None
184+
}
185+
}
186+
}
187+
155188
// FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the
156189
// HIR instead of the syntax tree.
157190
fn hints(
@@ -160,35 +193,8 @@ fn hints(
160193
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
161194
config: &InlayHintsConfig,
162195
file_id: EditionedFileId,
163-
node: WalkEvent<SyntaxNode>,
196+
node: SyntaxNode,
164197
) {
165-
let node = match node {
166-
WalkEvent::Enter(node) => node,
167-
WalkEvent::Leave(n) => {
168-
if ast::AnyHasGenericParams::can_cast(n.kind()) {
169-
ctx.lifetime_stacks.pop();
170-
// pop
171-
}
172-
if ast::ParamList::can_cast(n.kind()) {
173-
ctx.is_param_list = false;
174-
// pop
175-
}
176-
return;
177-
}
178-
};
179-
180-
if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) {
181-
let params = node
182-
.generic_param_list()
183-
.map(|it| {
184-
it.lifetime_params()
185-
.filter_map(|it| it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..])))
186-
.collect()
187-
})
188-
.unwrap_or_default();
189-
ctx.lifetime_stacks.push(params);
190-
}
191-
192198
closing_brace::hints(hints, sema, config, file_id, node.clone());
193199
if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
194200
generic_param::hints(hints, sema, config, any_has_generic_args);
@@ -242,10 +248,6 @@ fn hints(
242248
ast::Type::PathType(path) => lifetime::fn_path_hints(hints, ctx, famous_defs, config, file_id, path),
243249
_ => Some(()),
244250
},
245-
ast::ParamList(_) => {
246-
ctx.is_param_list = true;
247-
Some(())
248-
},
249251
_ => Some(()),
250252
}
251253
};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ fn fn_ptr(a: fn(&()) -> &fn(&()) -> &()) {}
532532
//^^ for<'1>
533533
//^'1
534534
//^'1
535-
fn fn_ptr2(a: for<'a> fn(&()) -> &())) {}
535+
fn fn_ptr2(a: for<'a> fn(&()) -> &()) {}
536536
//^'0, $
537537
//^'0
538538
//^'0

0 commit comments

Comments
 (0)