Skip to content

Commit 4b0c976

Browse files
bors[bot]matklad
andauthored
Merge #9772
9772: feat: filter out duplicate macro completions r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2 parents 2da06c1 + 2f92736 commit 4b0c976

File tree

13 files changed

+133
-95
lines changed

13 files changed

+133
-95
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ arrayvec = "0.7"
1616
itertools = "0.10.0"
1717
smallvec = "1.4.0"
1818
once_cell = "1"
19+
indexmap = "1.7"
1920

2021
stdx = { path = "../stdx", version = "0.0.0" }
2122
syntax = { path = "../syntax", version = "0.0.0" }

crates/hir/src/semantics.rs

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -923,31 +923,28 @@ impl<'a> SemanticsScope<'a> {
923923
}
924924

925925
pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
926-
let resolver = &self.resolver;
927-
928-
resolver.process_all_names(self.db.upcast(), &mut |name, def| {
929-
let def = match def {
930-
resolver::ScopeDef::PerNs(it) => {
931-
let items = ScopeDef::all_items(it);
932-
for item in items {
933-
f(name.clone(), item);
926+
let scope = self.resolver.names_in_scope(self.db.upcast());
927+
for (name, entries) in scope {
928+
for entry in entries {
929+
let def = match entry {
930+
resolver::ScopeDef::ModuleDef(it) => ScopeDef::ModuleDef(it.into()),
931+
resolver::ScopeDef::MacroDef(it) => ScopeDef::MacroDef(it.into()),
932+
resolver::ScopeDef::Unknown => ScopeDef::Unknown,
933+
resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
934+
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
935+
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
936+
resolver::ScopeDef::Local(pat_id) => {
937+
let parent = self.resolver.body_owner().unwrap();
938+
ScopeDef::Local(Local { parent, pat_id })
934939
}
935-
return;
936-
}
937-
resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
938-
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
939-
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
940-
resolver::ScopeDef::Local(pat_id) => {
941-
let parent = resolver.body_owner().unwrap();
942-
ScopeDef::Local(Local { parent, pat_id })
943-
}
944-
resolver::ScopeDef::Label(label_id) => {
945-
let parent = resolver.body_owner().unwrap();
946-
ScopeDef::Label(Label { parent, label_id })
947-
}
948-
};
949-
f(name, def)
950-
})
940+
resolver::ScopeDef::Label(label_id) => {
941+
let parent = self.resolver.body_owner().unwrap();
942+
ScopeDef::Label(Label { parent, label_id })
943+
}
944+
};
945+
f(name.clone(), def)
946+
}
947+
}
951948
}
952949

953950
/// Resolve a path as-if it was written at the given scope. This is

crates/hir_def/src/resolver.rs

Lines changed: 106 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use hir_expand::{
66
name::{name, Name},
77
MacroDefId,
88
};
9+
use indexmap::IndexMap;
910
use rustc_hash::FxHashSet;
11+
use smallvec::SmallVec;
1012

1113
use crate::{
1214
body::scope::{ExprScopes, ScopeId},
@@ -348,10 +350,50 @@ impl Resolver {
348350
item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
349351
}
350352

351-
pub fn process_all_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
353+
/// Returns a set of names available in the current scope.
354+
///
355+
/// Note that this is a somewhat fuzzy concept -- internally, the compiler
356+
/// doesn't necessary follow a strict scoping discipline. Rathe, it just
357+
/// tells for each ident what it resolves to.
358+
///
359+
/// A good example is something like `str::from_utf8`. From scopes point of
360+
/// view, this code is erroneous -- both `str` module and `str` type occupy
361+
/// the same type namespace.
362+
///
363+
/// We don't try to model that super-correctly -- this functionality is
364+
/// primarily exposed for completions.
365+
///
366+
/// Note that in Rust one name can be bound to several items:
367+
///
368+
/// ```
369+
/// macro_rules! t { () => (()) }
370+
/// type t = t!();
371+
/// const t: t = t!()
372+
/// ```
373+
///
374+
/// That's why we return a multimap.
375+
///
376+
/// The shadowing is accounted for: in
377+
///
378+
/// ```
379+
/// let x = 92;
380+
/// {
381+
/// let x = 92;
382+
/// $0
383+
/// }
384+
/// ```
385+
///
386+
/// there will be only one entry for `x` in the result.
387+
///
388+
/// The result is ordered *roughly* from the innermost scope to the
389+
/// outermost: when the name is introduced in two namespaces in two scopes,
390+
/// we use the position of the first scope.
391+
pub fn names_in_scope(&self, db: &dyn DefDatabase) -> IndexMap<Name, SmallVec<[ScopeDef; 1]>> {
392+
let mut res = ScopeNames::default();
352393
for scope in self.scopes() {
353-
scope.process_names(db, f);
394+
scope.process_names(db, &mut res);
354395
}
396+
res.map
355397
}
356398

357399
pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
@@ -434,8 +476,11 @@ impl Resolver {
434476
}
435477
}
436478

479+
#[derive(Debug, PartialEq, Eq)]
437480
pub enum ScopeDef {
438-
PerNs(PerNs),
481+
ModuleDef(ModuleDefId),
482+
MacroDef(MacroDefId),
483+
Unknown,
439484
ImplSelfType(ImplId),
440485
AdtSelfType(AdtId),
441486
GenericParam(GenericParamId),
@@ -444,8 +489,7 @@ pub enum ScopeDef {
444489
}
445490

446491
impl Scope {
447-
fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
448-
let mut seen = FxHashSet::default();
492+
fn process_names(&self, db: &dyn DefDatabase, acc: &mut ScopeNames) {
449493
match self {
450494
Scope::ModuleScope(m) => {
451495
// FIXME: should we provide `self` here?
@@ -456,58 +500,53 @@ impl Scope {
456500
// }),
457501
// );
458502
m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
459-
f(name.clone(), ScopeDef::PerNs(def));
503+
acc.add_per_ns(name, def);
460504
});
461-
m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
462-
let scope = PerNs::macros(macro_, Visibility::Public);
463-
seen.insert((name.clone(), scope));
464-
f(name.clone(), ScopeDef::PerNs(scope));
505+
m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, mac)| {
506+
acc.add(name, ScopeDef::MacroDef(mac));
465507
});
466508
m.def_map.extern_prelude().for_each(|(name, &def)| {
467-
f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
509+
acc.add(name, ScopeDef::ModuleDef(def));
468510
});
469511
BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
470-
f(name.clone(), ScopeDef::PerNs(def));
512+
acc.add_per_ns(name, def);
471513
});
472514
if let Some(prelude) = m.def_map.prelude() {
473515
let prelude_def_map = prelude.def_map(db);
474-
prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
475-
let seen_tuple = (name.clone(), def);
476-
if !seen.contains(&seen_tuple) {
477-
f(seen_tuple.0, ScopeDef::PerNs(def));
478-
}
479-
});
516+
for (name, def) in prelude_def_map[prelude.local_id].scope.entries() {
517+
acc.add_per_ns(name, def)
518+
}
480519
}
481520
}
482521
Scope::GenericParams { params, def: parent } => {
483522
let parent = *parent;
484523
for (local_id, param) in params.types.iter() {
485-
if let Some(ref name) = param.name {
524+
if let Some(name) = &param.name {
486525
let id = TypeParamId { parent, local_id };
487-
f(name.clone(), ScopeDef::GenericParam(id.into()))
526+
acc.add(name, ScopeDef::GenericParam(id.into()))
488527
}
489528
}
490529
for (local_id, param) in params.consts.iter() {
491530
let id = ConstParamId { parent, local_id };
492-
f(param.name.clone(), ScopeDef::GenericParam(id.into()))
531+
acc.add(&param.name, ScopeDef::GenericParam(id.into()))
493532
}
494533
for (local_id, param) in params.lifetimes.iter() {
495534
let id = LifetimeParamId { parent, local_id };
496-
f(param.name.clone(), ScopeDef::GenericParam(id.into()))
535+
acc.add(&param.name, ScopeDef::GenericParam(id.into()))
497536
}
498537
}
499538
Scope::ImplDefScope(i) => {
500-
f(name![Self], ScopeDef::ImplSelfType(*i));
539+
acc.add(&name![Self], ScopeDef::ImplSelfType(*i));
501540
}
502541
Scope::AdtScope(i) => {
503-
f(name![Self], ScopeDef::AdtSelfType(*i));
542+
acc.add(&name![Self], ScopeDef::AdtSelfType(*i));
504543
}
505544
Scope::ExprScope(scope) => {
506545
if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) {
507-
f(name, ScopeDef::Label(label))
546+
acc.add(&name, ScopeDef::Label(label))
508547
}
509548
scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
510-
f(e.name().clone(), ScopeDef::Local(e.pat()));
549+
acc.add_local(e.name(), e.pat());
511550
});
512551
}
513552
}
@@ -651,6 +690,47 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
651690
Some(res)
652691
}
653692

693+
#[derive(Default)]
694+
struct ScopeNames {
695+
map: IndexMap<Name, SmallVec<[ScopeDef; 1]>>,
696+
}
697+
698+
impl ScopeNames {
699+
fn add(&mut self, name: &Name, def: ScopeDef) {
700+
let set = self.map.entry(name.clone()).or_default();
701+
if !set.contains(&def) {
702+
set.push(def)
703+
}
704+
}
705+
fn add_per_ns(&mut self, name: &Name, def: PerNs) {
706+
if let Some(ty) = &def.types {
707+
self.add(name, ScopeDef::ModuleDef(ty.0))
708+
}
709+
if let Some(val) = &def.values {
710+
self.add(name, ScopeDef::ModuleDef(val.0))
711+
}
712+
if let Some(mac) = &def.macros {
713+
self.add(name, ScopeDef::MacroDef(mac.0))
714+
}
715+
if def.is_none() {
716+
self.add(name, ScopeDef::Unknown)
717+
}
718+
}
719+
fn add_local(&mut self, name: &Name, pat: PatId) {
720+
let set = self.map.entry(name.clone()).or_default();
721+
// XXX: hack, account for local (and only local) shadowing.
722+
//
723+
// This should be somewhat more principled and take namespaces into
724+
// accounts, but, alas, scoping rules are a hoax. `str` type and `str`
725+
// module can be both available in the same scope.
726+
if set.iter().any(|it| matches!(it, &ScopeDef::Local(_))) {
727+
cov_mark::hit!(shadowing_shows_single_completion);
728+
return;
729+
}
730+
set.push(ScopeDef::Local(pat))
731+
}
732+
}
733+
654734
pub trait HasResolver: Copy {
655735
/// Builds a resolver for type references inside this def.
656736
fn resolver(self, db: &dyn DefDatabase) -> Resolver;

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -304,25 +304,4 @@ pub mod prelude {
304304
"#]],
305305
);
306306
}
307-
308-
#[test]
309-
fn local_variable_shadowing() {
310-
// FIXME: this isn't actually correct, should emit `x` only once.
311-
check(
312-
r#"
313-
fn main() {
314-
let x = 92;
315-
{
316-
let x = 92;
317-
x$0;
318-
}
319-
}
320-
"#,
321-
expect![[r#"
322-
lc x i32
323-
lc x i32
324-
fn main() fn()
325-
"#]],
326-
);
327-
}
328307
}

crates/ide_completion/src/render.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1348,10 +1348,10 @@ fn foo() {
13481348
lc foo [type+local]
13491349
ev Foo::A(…) [type_could_unify]
13501350
ev Foo::B [type_could_unify]
1351+
fn foo() []
13511352
en Foo []
13521353
fn baz() []
13531354
fn bar() []
1354-
fn foo() []
13551355
"#]],
13561356
);
13571357
}

crates/ide_completion/src/tests/expression.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ impl Unit {
118118
un Union
119119
ev TupleV(…) (u32)
120120
ct CONST
121-
ma makro!(…) #[macro_export] macro_rules! makro
122121
me self.foo() fn(self)
123122
"##]],
124123
);
@@ -155,6 +154,8 @@ impl Unit {
155154

156155
#[test]
157156
fn shadowing_shows_single_completion() {
157+
cov_mark::check!(shadowing_shows_single_completion);
158+
158159
check_empty(
159160
r#"
160161
fn foo() {
@@ -165,7 +166,6 @@ fn foo() {
165166
}
166167
}
167168
"#,
168-
// FIXME: should be only one bar here
169169
expect![[r#"
170170
kw unsafe
171171
kw match
@@ -182,7 +182,6 @@ fn foo() {
182182
kw super
183183
kw crate
184184
lc bar i32
185-
lc bar i32
186185
fn foo() fn()
187186
bt u32
188187
"#]],

crates/ide_completion/src/tests/item.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ impl Tra$0
2929
st Unit
3030
ma makro!(…) #[macro_export] macro_rules! makro
3131
un Union
32-
ma makro!(…) #[macro_export] macro_rules! makro
3332
bt u32
3433
"##]],
3534
)
@@ -53,7 +52,6 @@ impl Trait for Str$0
5352
st Unit
5453
ma makro!(…) #[macro_export] macro_rules! makro
5554
un Union
56-
ma makro!(…) #[macro_export] macro_rules! makro
5755
bt u32
5856
"##]],
5957
)

crates/ide_completion/src/tests/item_list.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ fn in_source_file_item_list() {
6767
kw crate
6868
md module
6969
ma makro!(…) #[macro_export] macro_rules! makro
70-
ma makro!(…) #[macro_export] macro_rules! makro
7170
"##]],
7271
)
7372
}
@@ -172,7 +171,6 @@ fn in_impl_assoc_item_list() {
172171
kw crate
173172
md module
174173
ma makro!(…) #[macro_export] macro_rules! makro
175-
ma makro!(…) #[macro_export] macro_rules! makro
176174
"##]],
177175
)
178176
}
@@ -206,7 +204,6 @@ fn in_trait_assoc_item_list() {
206204
kw crate
207205
md module
208206
ma makro!(…) #[macro_export] macro_rules! makro
209-
ma makro!(…) #[macro_export] macro_rules! makro
210207
"##]],
211208
);
212209
}
@@ -243,7 +240,6 @@ impl Test for () {
243240
kw crate
244241
md module
245242
ma makro!(…) #[macro_export] macro_rules! makro
246-
ma makro!(…) #[macro_export] macro_rules! makro
247243
"##]],
248244
);
249245
}

0 commit comments

Comments
 (0)