Skip to content

Commit c296e77

Browse files
committed
Auto merge of rust-lang#12695 - xuhongxu96:fix-12140, r=jonas-schievink
Complete type param/associated type in trait generic arg per arg index - Fix rust-lang#12140 - Also fix tidy check does not work for marks in multiline
2 parents c46570e + 3248601 commit c296e77

File tree

5 files changed

+347
-50
lines changed

5 files changed

+347
-50
lines changed

crates/hir-def/src/generics.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct LifetimeParamData {
4747
pub struct ConstParamData {
4848
pub name: Name,
4949
pub ty: Interned<TypeRef>,
50+
pub has_default: bool,
5051
}
5152

5253
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -70,6 +71,13 @@ impl TypeOrConstParamData {
7071
}
7172
}
7273

74+
pub fn has_default(&self) -> bool {
75+
match self {
76+
TypeOrConstParamData::TypeParamData(x) => x.default.is_some(),
77+
TypeOrConstParamData::ConstParamData(x) => x.has_default,
78+
}
79+
}
80+
7381
pub fn type_param(&self) -> Option<&TypeParamData> {
7482
match self {
7583
TypeOrConstParamData::TypeParamData(x) => Some(x),
@@ -232,7 +240,11 @@ impl GenericParams {
232240
let ty = const_param
233241
.ty()
234242
.map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
235-
let param = ConstParamData { name, ty: Interned::new(ty) };
243+
let param = ConstParamData {
244+
name,
245+
ty: Interned::new(ty),
246+
has_default: const_param.default_val().is_some(),
247+
};
236248
self.type_or_consts.alloc(param.into());
237249
}
238250
}

crates/hir/src/lib.rs

+21
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use hir_def::{
4141
adt::{ReprKind, VariantData},
4242
body::{BodyDiagnostic, SyntheticSyntax},
4343
expr::{BindingAnnotation, LabelId, Pat, PatId},
44+
generics::{TypeOrConstParamData, TypeParamProvenance},
4445
item_tree::ItemTreeNode,
4546
lang_item::LangItemTarget,
4647
nameres::{self, diagnostics::DefDiagnostic},
@@ -1707,6 +1708,26 @@ impl Trait {
17071708
pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
17081709
db.trait_data(self.id).is_unsafe
17091710
}
1711+
1712+
pub fn type_or_const_param_count(
1713+
&self,
1714+
db: &dyn HirDatabase,
1715+
count_required_only: bool,
1716+
) -> usize {
1717+
db.generic_params(GenericDefId::from(self.id))
1718+
.type_or_consts
1719+
.iter()
1720+
.filter(|(_, ty)| match ty {
1721+
TypeOrConstParamData::TypeParamData(ty)
1722+
if ty.provenance != TypeParamProvenance::TypeParamList =>
1723+
{
1724+
false
1725+
}
1726+
_ => true,
1727+
})
1728+
.filter(|(_, ty)| !count_required_only || !ty.has_default())
1729+
.count()
1730+
}
17101731
}
17111732

17121733
impl HasVisibility for Trait {

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

+73-29
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};
4+
use syntax::{ast, AstNode, SyntaxKind};
55

66
use crate::{
77
context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
@@ -120,39 +120,83 @@ pub(crate) fn complete_type_path(
120120
}
121121
Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
122122
Qualified::No => {
123-
acc.add_nameref_keywords_with_colon(ctx);
124-
if let TypeLocation::TypeBound = location {
125-
ctx.process_all_names(&mut |name, res| {
126-
let add_resolution = match res {
127-
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
128-
ScopeDef::ModuleDef(
129-
hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
130-
) => true,
131-
_ => false,
132-
};
133-
if add_resolution {
134-
acc.add_path_resolution(ctx, path_ctx, name, res);
135-
}
136-
});
137-
return;
138-
}
139-
if let TypeLocation::GenericArgList(Some(arg_list)) = location {
140-
if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast)
141-
{
142-
if path_seg.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() {
143-
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
144-
ctx.sema.resolve_path(&path_seg.parent_path())
123+
match location {
124+
TypeLocation::TypeBound => {
125+
acc.add_nameref_keywords_with_colon(ctx);
126+
ctx.process_all_names(&mut |name, res| {
127+
let add_resolution = match res {
128+
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
129+
mac.is_fn_like(ctx.db)
130+
}
131+
ScopeDef::ModuleDef(
132+
hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
133+
) => true,
134+
_ => false,
135+
};
136+
if add_resolution {
137+
acc.add_path_resolution(ctx, path_ctx, name, res);
138+
}
139+
});
140+
return;
141+
}
142+
TypeLocation::GenericArgList(Some(arg_list)) => {
143+
let in_assoc_type_arg = ctx
144+
.original_token
145+
.parent_ancestors()
146+
.any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
147+
148+
if !in_assoc_type_arg {
149+
if let Some(path_seg) =
150+
arg_list.syntax().parent().and_then(ast::PathSegment::cast)
145151
{
146-
trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| {
147-
if let hir::AssocItem::TypeAlias(alias) = it {
148-
cov_mark::hit!(complete_assoc_type_in_generics_list);
149-
acc.add_type_alias_with_eq(ctx, alias)
152+
if path_seg
153+
.syntax()
154+
.ancestors()
155+
.find_map(ast::TypeBound::cast)
156+
.is_some()
157+
{
158+
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
159+
trait_,
160+
))) = ctx.sema.resolve_path(&path_seg.parent_path())
161+
{
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_
174+
.items_with_supertraits(ctx.sema.db)
175+
.into_iter()
176+
.for_each(|it| {
177+
if let hir::AssocItem::TypeAlias(alias) = it {
178+
cov_mark::hit!(
179+
complete_assoc_type_in_generics_list
180+
);
181+
acc.add_type_alias_with_eq(ctx, alias);
182+
}
183+
});
184+
185+
let n_params =
186+
trait_.type_or_const_param_count(ctx.sema.db, false);
187+
if arg_idx >= n_params {
188+
return; // only show assoc types
189+
}
190+
}
150191
}
151-
});
192+
}
152193
}
153194
}
154195
}
155-
}
196+
_ => {}
197+
};
198+
199+
acc.add_nameref_keywords_with_colon(ctx);
156200
ctx.process_all_names(&mut |name, def| {
157201
if scope_def_applicable(def) {
158202
acc.add_path_resolution(ctx, path_ctx, name, def);

0 commit comments

Comments
 (0)