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

Commit bb9d822

Browse files
committed
cleanup
1 parent bed1114 commit bb9d822

File tree

5 files changed

+120
-111
lines changed

5 files changed

+120
-111
lines changed

crates/ide-completion/src/completions.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,9 @@ pub(super) fn complete_name_ref(
703703
TypeLocation::TypeAscription(ascription) => {
704704
r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
705705
}
706-
TypeLocation::GenericArgList(_)
706+
TypeLocation::GenericArg(_)
707+
| TypeLocation::AssocConstEq
708+
| TypeLocation::AssocTypeEq
707709
| TypeLocation::TypeBound
708710
| TypeLocation::ImplTarget
709711
| TypeLocation::ImplTrait

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

Lines changed: 33 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Completion of names from the current scope in type position.
22
33
use hir::{HirDisplay, ScopeDef};
4-
use syntax::{ast, AstNode, SyntaxKind};
4+
use syntax::{ast, AstNode};
55

66
use crate::{
77
context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
@@ -20,36 +20,15 @@ pub(crate) fn complete_type_path(
2020
let scope_def_applicable = |def| {
2121
use hir::{GenericParam::*, ModuleDef::*};
2222
match def {
23-
ScopeDef::GenericParam(LifetimeParam(_)) => {
24-
matches!(
25-
location,
26-
TypeLocation::GenericArgList(Some((
27-
_,
28-
Some(ast::GenericParam::LifetimeParam(_))
29-
)))
30-
)
31-
}
23+
ScopeDef::GenericParam(LifetimeParam(_)) => location.complete_lifetimes(),
3224
ScopeDef::Label(_) => false,
3325
// no values in type places
3426
ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
3527
// unless its a constant in a generic arg list position
36-
ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => match location
37-
{
38-
TypeLocation::GenericArgList(location) => match location {
39-
Some((_, Some(generic_param))) => {
40-
matches!(generic_param, ast::GenericParam::ConstParam(_))
41-
}
42-
_ => true,
43-
},
44-
_ => false,
45-
},
46-
ScopeDef::ImplSelfType(_) => match location {
47-
TypeLocation::ImplTarget | TypeLocation::ImplTrait => false,
48-
TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => {
49-
matches!(generic_param, ast::GenericParam::TypeParam(_))
50-
}
51-
_ => true,
52-
},
28+
ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
29+
location.complete_consts()
30+
}
31+
ScopeDef::ImplSelfType(_) => location.complete_self_type(),
5332
// Don't suggest attribute macros and derives.
5433
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
5534
// Type things are fine
@@ -58,17 +37,12 @@ pub(crate) fn complete_type_path(
5837
)
5938
| ScopeDef::AdtSelfType(_)
6039
| ScopeDef::Unknown
61-
| ScopeDef::GenericParam(TypeParam(_)) => match location {
62-
TypeLocation::GenericArgList(Some((_, Some(generic_param)))) => {
63-
matches!(generic_param, ast::GenericParam::TypeParam(_))
64-
}
65-
_ => true,
66-
},
40+
| ScopeDef::GenericParam(TypeParam(_)) => location.complete_types(),
6741
}
6842
};
6943

7044
let add_assoc_item = |acc: &mut Completions, item| match item {
71-
hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArgList(_)) => {
45+
hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArg(_)) => {
7246
acc.add_const(ctx, ct)
7347
}
7448
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (),
@@ -182,55 +156,32 @@ pub(crate) fn complete_type_path(
182156
});
183157
return;
184158
}
185-
TypeLocation::GenericArgList(Some((arg_list, _))) => {
186-
let in_assoc_type_arg = ctx
187-
.original_token
188-
.parent_ancestors()
189-
.any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
190-
191-
if !in_assoc_type_arg {
192-
if let Some(path_seg) =
193-
arg_list.syntax().parent().and_then(ast::PathSegment::cast)
194-
{
195-
if path_seg
196-
.syntax()
197-
.ancestors()
198-
.find_map(ast::TypeBound::cast)
199-
.is_some()
200-
{
201-
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
202-
trait_,
203-
))) = ctx.sema.resolve_path(&path_seg.parent_path())
204-
{
205-
let arg_idx = arg_list
206-
.generic_args()
207-
.filter(|arg| {
208-
arg.syntax().text_range().end()
209-
< ctx.original_token.text_range().start()
210-
})
211-
.count();
212-
213-
let n_required_params =
214-
trait_.type_or_const_param_count(ctx.sema.db, true);
215-
if arg_idx >= n_required_params {
216-
trait_
217-
.items_with_supertraits(ctx.sema.db)
218-
.into_iter()
219-
.for_each(|it| {
220-
if let hir::AssocItem::TypeAlias(alias) = it {
221-
cov_mark::hit!(
222-
complete_assoc_type_in_generics_list
223-
);
224-
acc.add_type_alias_with_eq(ctx, alias);
225-
}
226-
});
227-
228-
let n_params =
229-
trait_.type_or_const_param_count(ctx.sema.db, false);
230-
if arg_idx >= n_params {
231-
return; // only show assoc types
159+
TypeLocation::GenericArg(Some((arg_list, in_trait, _))) => {
160+
if let Some(trait_) = in_trait {
161+
if arg_list.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() {
162+
let arg_idx = arg_list
163+
.generic_args()
164+
.filter(|arg| {
165+
arg.syntax().text_range().end()
166+
< ctx.original_token.text_range().start()
167+
})
168+
.count();
169+
170+
let n_required_params =
171+
trait_.type_or_const_param_count(ctx.sema.db, true);
172+
if arg_idx >= n_required_params {
173+
trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(
174+
|it| {
175+
if let hir::AssocItem::TypeAlias(alias) = it {
176+
cov_mark::hit!(complete_assoc_type_in_generics_list);
177+
acc.add_type_alias_with_eq(ctx, alias);
232178
}
233-
}
179+
},
180+
);
181+
182+
let n_params = trait_.type_or_const_param_count(ctx.sema.db, false);
183+
if arg_idx >= n_params {
184+
return; // only show assoc types
234185
}
235186
}
236187
}

crates/ide-completion/src/context.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,54 @@ pub(crate) struct ExprCtx {
155155
pub(crate) enum TypeLocation {
156156
TupleField,
157157
TypeAscription(TypeAscriptionTarget),
158-
GenericArgList(Option<(ast::GenericArgList, Option<ast::GenericParam>)>),
158+
/// Generic argument position e.g. `Foo<$0>`
159+
GenericArg(Option<(ast::GenericArgList, Option<hir::Trait>, Option<ast::GenericParam>)>),
160+
/// Associated type equality constraint e.g. `Foo<Bar = $0>`
161+
AssocTypeEq,
162+
/// Associated constant equality constraint e.g. `Foo<X = $0>`
163+
AssocConstEq,
159164
TypeBound,
160165
ImplTarget,
161166
ImplTrait,
162167
Other,
163168
}
164169

170+
impl TypeLocation {
171+
pub(crate) fn complete_lifetimes(&self) -> bool {
172+
match self {
173+
TypeLocation::GenericArg(Some((_, _, Some(param)))) => {
174+
matches!(param, ast::GenericParam::LifetimeParam(_))
175+
}
176+
_ => false,
177+
}
178+
}
179+
180+
pub(crate) fn complete_consts(&self) -> bool {
181+
match self {
182+
TypeLocation::GenericArg(Some((_, _, Some(param)))) => {
183+
matches!(param, ast::GenericParam::ConstParam(_))
184+
}
185+
TypeLocation::AssocConstEq => true,
186+
_ => false,
187+
}
188+
}
189+
190+
pub(crate) fn complete_types(&self) -> bool {
191+
match self {
192+
TypeLocation::GenericArg(Some((_, _, Some(param)))) => {
193+
matches!(param, ast::GenericParam::TypeParam(_))
194+
}
195+
TypeLocation::AssocConstEq => false,
196+
TypeLocation::AssocTypeEq => true,
197+
_ => true,
198+
}
199+
}
200+
201+
pub(crate) fn complete_self_type(&self) -> bool {
202+
self.complete_types() && !matches!(self, TypeLocation::ImplTarget | TypeLocation::ImplTrait)
203+
}
204+
}
205+
165206
#[derive(Clone, Debug, PartialEq, Eq)]
166207
pub(crate) enum TypeAscriptionTarget {
167208
Let(Option<ast::Pat>),

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

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -720,12 +720,14 @@ fn classify_name_ref(
720720
};
721721

722722
let generic_arg_location = |arg: ast::GenericArg| {
723+
let mut override_location = None;
723724
let location = find_opt_node_in_file_compensated(
724725
sema,
725726
original_file,
726727
arg.syntax().parent().and_then(ast::GenericArgList::cast),
727728
)
728729
.map(|args| {
730+
let mut in_trait = None;
729731
let param = (|| {
730732
let parent = args.syntax().parent()?;
731733
let params = match_ast! {
@@ -743,7 +745,31 @@ fn classify_name_ref(
743745
variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list()
744746
}
745747
hir::ModuleDef::Trait(trait_) => {
746-
trait_.source(sema.db)?.value.generic_param_list()
748+
if let ast::GenericArg::AssocTypeArg(arg) = &arg {
749+
let arg_name = arg.name_ref()?;
750+
let arg_name = arg_name.text();
751+
for item in trait_.items_with_supertraits(sema.db) {
752+
match item {
753+
hir::AssocItem::TypeAlias(assoc_ty) => {
754+
if assoc_ty.name(sema.db).as_str()? == arg_name {
755+
override_location = Some(TypeLocation::AssocTypeEq);
756+
return None;
757+
}
758+
},
759+
hir::AssocItem::Const(const_) => {
760+
if const_.name(sema.db)?.as_str()? == arg_name {
761+
override_location = Some(TypeLocation::AssocConstEq);
762+
return None;
763+
}
764+
},
765+
_ => (),
766+
}
767+
}
768+
return None;
769+
} else {
770+
in_trait = Some(trait_);
771+
trait_.source(sema.db)?.value.generic_param_list()
772+
}
747773
}
748774
hir::ModuleDef::TraitAlias(trait_) => {
749775
trait_.source(sema.db)?.value.generic_param_list()
@@ -765,10 +791,12 @@ fn classify_name_ref(
765791
match sema.resolve_path(&trait_.parent_path().top_path())? {
766792
hir::PathResolution::Def(def) => match def {
767793
hir::ModuleDef::Trait(trait_) => {
768-
let trait_items = trait_.items(sema.db);
794+
let arg_name = arg.name_ref()?;
795+
let arg_name = arg_name.text();
796+
let trait_items = trait_.items_with_supertraits(sema.db);
769797
let assoc_ty = trait_items.iter().find_map(|item| match item {
770798
hir::AssocItem::TypeAlias(assoc_ty) => {
771-
(assoc_ty.name(sema.db).as_str()? == arg.name_ref()?.text())
799+
(assoc_ty.name(sema.db).as_str()? == arg_name)
772800
.then_some(assoc_ty)
773801
},
774802
_ => None,
@@ -784,11 +812,10 @@ fn classify_name_ref(
784812
}
785813
}?;
786814
// 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`.
815+
// the corresponding parameter in the `GenericParamList`. Since lifetime parameters
816+
// are often omitted, ignore them for the purposes of matching the argument with
817+
// its parameter unless a lifetime argument is provided explicitly. That is, for
818+
// `struct S<'a, 'b, T>`, match `S::<$0>` to `T` and `S::<'a, $0, _>` to `'b`.
792819
let mut explicit_lifetime_arg = false;
793820
let arg_idx = arg
794821
.syntax()
@@ -806,9 +833,9 @@ fn classify_name_ref(
806833
};
807834
params.generic_params().nth(param_idx)
808835
})();
809-
(args, param)
836+
(args, in_trait, param)
810837
});
811-
TypeLocation::GenericArgList(location)
838+
override_location.unwrap_or(TypeLocation::GenericArg(location))
812839
};
813840

814841
let type_location = |node: &SyntaxNode| {
@@ -870,8 +897,8 @@ fn classify_name_ref(
870897
// is this case needed?
871898
ast::GenericArgList(it) => {
872899
let location = find_opt_node_in_file_compensated(sema, original_file, Some(it))
873-
.map(|node| (node, None));
874-
TypeLocation::GenericArgList(location)
900+
.map(|node| (node, None, None));
901+
TypeLocation::GenericArg(location)
875902
},
876903
ast::TupleField(_) => TypeLocation::TupleField,
877904
_ => return None,

crates/ide-completion/src/tests/type_pos.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -402,14 +402,13 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
402402
);
403403
check(
404404
r#"
405-
trait Trait2 {
405+
trait Trait2<T> {
406406
type Foo;
407407
}
408408
409409
fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {}
410410
"#,
411411
expect![[r#"
412-
ct CONST
413412
en Enum
414413
ma makro!(…) macro_rules! makro
415414
md module
@@ -620,7 +619,6 @@ trait MyTrait {
620619
fn f(t: impl MyTrait<Item1 = $0
621620
"#,
622621
expect![[r#"
623-
ct CONST
624622
en Enum
625623
ma makro!(…) macro_rules! makro
626624
md module
@@ -639,24 +637,14 @@ fn f(t: impl MyTrait<Item1 = $0
639637
check(
640638
r#"
641639
trait MyTrait {
642-
type Item1;
643-
type Item2;
640+
const C: usize;
644641
};
645642
646-
fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
643+
fn f(t: impl MyTrait<C = $0
647644
"#,
648645
expect![[r#"
649646
ct CONST
650-
en Enum
651647
ma makro!(…) macro_rules! makro
652-
md module
653-
st Record
654-
st Tuple
655-
st Unit
656-
tt MyTrait
657-
tt Trait
658-
un Union
659-
bt u32
660648
kw crate::
661649
kw self::
662650
"#]],

0 commit comments

Comments
 (0)