Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bed1114

Browse files
committed
handle omitted lifetime params
1 parent d48606f commit bed1114

File tree

3 files changed

+221
-155
lines changed

3 files changed

+221
-155
lines changed

crates/ide-completion/src/completions/type.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,16 @@ pub(crate) fn complete_type_path(
2020
let scope_def_applicable = |def| {
2121
use hir::{GenericParam::*, ModuleDef::*};
2222
match def {
23-
ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
23+
ScopeDef::GenericParam(LifetimeParam(_)) => {
24+
matches!(
25+
location,
26+
TypeLocation::GenericArgList(Some((
27+
_,
28+
Some(ast::GenericParam::LifetimeParam(_))
29+
)))
30+
)
31+
}
32+
ScopeDef::Label(_) => false,
2433
// no values in type places
2534
ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
2635
// unless its a constant in a generic arg list position

crates/ide-completion/src/context/analysis.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,9 +783,27 @@ fn classify_name_ref(
783783
_ => None,
784784
}
785785
}?;
786-
// Determine the index of the parameter in the `GenericArgList`
787-
// (subtract 1 because `siblings` includes the node itself)
788-
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
786+
// Determine the index of the argument in the `GenericArgList` and match it with
787+
// the corresponding parameter in the `GenericParamList`.
788+
// Since lifetime parameters are often omitted, ignore them for the purposes of
789+
// matching the argument with its parameter unless a lifetime argument is provided
790+
// explicitly. That is, for `struct S<'a, 'b, T>`, match `S::<$0>` to to `T` and
791+
// `S::<'a, $0, _>` to `'b`.
792+
let mut explicit_lifetime_arg = false;
793+
let arg_idx = arg
794+
.syntax()
795+
.siblings(Direction::Prev)
796+
// Skip the node itself
797+
.skip(1)
798+
.map(|arg| if ast::LifetimeArg::can_cast(arg.kind()) { explicit_lifetime_arg = true })
799+
.count();
800+
let param_idx = if explicit_lifetime_arg {
801+
arg_idx
802+
} else {
803+
// Lifetimes parameters always precede type and generic parameters,
804+
// so offset the argument index by the total number of lifetime params
805+
arg_idx + params.lifetime_params().count()
806+
};
789807
params.generic_params().nth(param_idx)
790808
})();
791809
(args, param)

0 commit comments

Comments
 (0)