Skip to content

Commit e471ea8

Browse files
committed
resolve: Introduce ScopeSet::Module
for looking up a name in two scopes insice a module - non-glob and glob bindings.
1 parent 07d616f commit e471ea8

File tree

5 files changed

+107
-110
lines changed

5 files changed

+107
-110
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 73 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
114114

115115
let rust_2015 = ctxt.edition().is_rust_2015();
116116
let (ns, macro_kind) = match scope_set {
117-
ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
117+
ScopeSet::All(ns)
118+
| ScopeSet::Module(ns, _)
119+
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
118120
ScopeSet::ExternPrelude => (TypeNS, None),
119121
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
120122
};
121123
let module = match scope_set {
122124
// Start with the specified module.
123-
ScopeSet::ModuleAndExternPrelude(_, module) => module,
125+
ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => module,
124126
// Jump out of trait or enum modules, they do not act as scopes.
125127
_ => parent_scope.module.nearest_item_scope(),
126128
};
129+
let module_only = matches!(scope_set, ScopeSet::Module(..));
127130
let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
128131
let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);
129132
let mut scope = match ns {
130-
_ if module_and_extern_prelude => Scope::ModuleNonGlobs(module, None),
133+
_ if module_only || module_and_extern_prelude => Scope::ModuleNonGlobs(module, None),
131134
_ if extern_prelude => Scope::ExternPreludeItems,
132135
TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None),
133136
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
@@ -200,6 +203,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
200203
MacroRulesScope::Empty => Scope::ModuleNonGlobs(module, None),
201204
},
202205
Scope::ModuleNonGlobs(module, lint_id) => Scope::ModuleGlobs(module, lint_id),
206+
Scope::ModuleGlobs(..) if module_only => break,
203207
Scope::ModuleGlobs(..) if module_and_extern_prelude => match ns {
204208
TypeNS => {
205209
ctxt.adjust(ExpnId::root());
@@ -348,13 +352,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
348352
diag_metadata,
349353
)));
350354
} else if let RibKind::Block(Some(module)) = rib.kind
351-
&& let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
352-
module,
355+
&& let Ok(binding) = self.cm().resolve_ident_in_scope_set(
353356
ident,
354-
ns,
357+
ScopeSet::Module(ns, module),
355358
parent_scope,
356-
Shadowing::Unrestricted,
357359
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
360+
finalize.is_some(),
358361
ignore_binding,
359362
None,
360363
)
@@ -407,12 +410,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
407410
assert!(force || finalize.is_none()); // `finalize` implies `force`
408411

409412
// Make sure `self`, `super` etc produce an error when passed to here.
410-
if orig_ident.is_path_segment_keyword() {
413+
if orig_ident.is_path_segment_keyword() && !matches!(scope_set, ScopeSet::Module(..)) {
411414
return Err(Determinacy::Determined);
412415
}
413416

414417
let (ns, macro_kind) = match scope_set {
415-
ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
418+
ScopeSet::All(ns)
419+
| ScopeSet::Module(ns, _)
420+
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
416421
ScopeSet::ExternPrelude => (TypeNS, None),
417422
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
418423
};
@@ -586,21 +591,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
586591
_ => Err(Determinacy::Determined),
587592
},
588593
Scope::ModuleNonGlobs(module, derive_fallback_lint_id) => {
589-
let (adjusted_parent_scope, adjusted_finalize) =
590-
if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
591-
(parent_scope, finalize)
592-
} else {
593-
(
594-
&ParentScope { module, ..*parent_scope },
595-
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
596-
)
597-
};
594+
let (adjusted_parent_scope, adjusted_finalize) = if matches!(
595+
scope_set,
596+
ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..)
597+
) {
598+
(parent_scope, finalize)
599+
} else {
600+
(
601+
&ParentScope { module, ..*parent_scope },
602+
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
603+
)
604+
};
598605
let binding = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
599606
module,
600607
ident,
601608
ns,
602609
adjusted_parent_scope,
603-
Shadowing::Restricted,
610+
if matches!(scope_set, ScopeSet::Module(..)) {
611+
Shadowing::Unrestricted
612+
} else {
613+
Shadowing::Restricted
614+
},
604615
adjusted_finalize,
605616
ignore_binding,
606617
ignore_import,
@@ -629,29 +640,35 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
629640
Ok((binding, Flags::MODULE | misc_flags))
630641
}
631642
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
632-
Err(ControlFlow::Break(Determinacy::Undetermined)) => {
633-
return Err(ControlFlow::Break(Determinacy::determined(force)));
643+
Err(ControlFlow::Break(determinacy)) => {
644+
return Err(ControlFlow::Break(Determinacy::determined(
645+
determinacy == Determinacy::Determined || force,
646+
)));
634647
}
635-
// Privacy errors, do not happen during in scope resolution.
636-
Err(ControlFlow::Break(Determinacy::Determined)) => unreachable!(),
637648
}
638649
}
639650
Scope::ModuleGlobs(module, derive_fallback_lint_id) => {
640-
let (adjusted_parent_scope, adjusted_finalize) =
641-
if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
642-
(parent_scope, finalize)
643-
} else {
644-
(
645-
&ParentScope { module, ..*parent_scope },
646-
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
647-
)
648-
};
651+
let (adjusted_parent_scope, adjusted_finalize) = if matches!(
652+
scope_set,
653+
ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..)
654+
) {
655+
(parent_scope, finalize)
656+
} else {
657+
(
658+
&ParentScope { module, ..*parent_scope },
659+
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
660+
)
661+
};
649662
let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted(
650663
module,
651664
ident,
652665
ns,
653666
adjusted_parent_scope,
654-
Shadowing::Restricted,
667+
if matches!(scope_set, ScopeSet::Module(..)) {
668+
Shadowing::Unrestricted
669+
} else {
670+
Shadowing::Restricted
671+
},
655672
adjusted_finalize,
656673
ignore_binding,
657674
ignore_import,
@@ -680,11 +697,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
680697
Ok((binding, Flags::MODULE | misc_flags))
681698
}
682699
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
683-
Err(ControlFlow::Break(Determinacy::Undetermined)) => {
684-
return Err(ControlFlow::Break(Determinacy::determined(force)));
700+
Err(ControlFlow::Break(determinacy)) => {
701+
return Err(ControlFlow::Break(Determinacy::determined(
702+
determinacy == Determinacy::Determined || force,
703+
)));
685704
}
686-
// Privacy errors, do not happen during in scope resolution.
687-
Err(ControlFlow::Break(Determinacy::Determined)) => unreachable!(),
688705
}
689706
}
690707
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
@@ -724,13 +741,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
724741
Scope::StdLibPrelude => {
725742
let mut result = Err(Determinacy::Determined);
726743
if let Some(prelude) = self.prelude
727-
&& let Ok(binding) = self.reborrow().resolve_ident_in_module_unadjusted(
728-
prelude,
744+
&& let Ok(binding) = self.reborrow().resolve_ident_in_scope_set(
729745
ident,
730-
ns,
746+
ScopeSet::Module(ns, prelude),
731747
parent_scope,
732-
Shadowing::Unrestricted,
733748
None,
749+
false,
734750
ignore_binding,
735751
ignore_import,
736752
)
@@ -937,18 +953,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
937953
ignore_import: Option<Import<'ra>>,
938954
) -> Result<NameBinding<'ra>, Determinacy> {
939955
match module {
940-
ModuleOrUniformRoot::Module(module) => self
941-
.resolve_ident_in_module_unadjusted(
942-
module,
943-
ident,
944-
ns,
945-
parent_scope,
946-
Shadowing::Unrestricted,
947-
finalize,
948-
ignore_binding,
949-
ignore_import,
950-
)
951-
.map_err(|determinacy| determinacy.into_value()),
956+
ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set(
957+
ident,
958+
ScopeSet::Module(ns, module),
959+
parent_scope,
960+
finalize,
961+
finalize.is_some(),
962+
ignore_binding,
963+
ignore_import,
964+
),
952965
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
953966
ident,
954967
ScopeSet::ModuleAndExternPrelude(ns, module),
@@ -998,48 +1011,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9981011
}
9991012
}
10001013

1001-
/// Attempts to resolve `ident` in namespace `ns` of `module`.
1002-
fn resolve_ident_in_module_unadjusted<'r>(
1003-
mut self: CmResolver<'r, 'ra, 'tcx>,
1004-
module: Module<'ra>,
1005-
ident: Ident,
1006-
ns: Namespace,
1007-
parent_scope: &ParentScope<'ra>,
1008-
shadowing: Shadowing,
1009-
finalize: Option<Finalize>,
1010-
// This binding should be ignored during in-module resolution, so that we don't get
1011-
// "self-confirming" import resolutions during import validation and checking.
1012-
ignore_binding: Option<NameBinding<'ra>>,
1013-
ignore_import: Option<Import<'ra>>,
1014-
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
1015-
let res = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
1016-
module,
1017-
ident,
1018-
ns,
1019-
parent_scope,
1020-
shadowing,
1021-
finalize,
1022-
ignore_binding,
1023-
ignore_import,
1024-
);
1025-
1026-
match res {
1027-
Ok(_) | Err(ControlFlow::Break(_)) => return res,
1028-
Err(ControlFlow::Continue(_)) => {}
1029-
}
1030-
1031-
self.resolve_ident_in_module_globs_unadjusted(
1032-
module,
1033-
ident,
1034-
ns,
1035-
parent_scope,
1036-
shadowing,
1037-
finalize,
1038-
ignore_binding,
1039-
ignore_import,
1040-
)
1041-
}
1042-
10431014
/// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`.
10441015
fn resolve_ident_in_module_non_globs_unadjusted<'r>(
10451016
mut self: CmResolver<'r, 'ra, 'tcx>,
@@ -1049,6 +1020,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10491020
parent_scope: &ParentScope<'ra>,
10501021
shadowing: Shadowing,
10511022
finalize: Option<Finalize>,
1023+
// This binding should be ignored during in-module resolution, so that we don't get
1024+
// "self-confirming" import resolutions during import validation and checking.
10521025
ignore_binding: Option<NameBinding<'ra>>,
10531026
ignore_import: Option<Import<'ra>>,
10541027
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
@@ -1206,28 +1179,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12061179
Some(None) => {}
12071180
None => continue,
12081181
};
1209-
let result = self.reborrow().resolve_ident_in_module_unadjusted(
1210-
module,
1182+
let result = self.reborrow().resolve_ident_in_scope_set(
12111183
ident,
1212-
ns,
1184+
ScopeSet::Module(ns, module),
12131185
adjusted_parent_scope,
1214-
Shadowing::Unrestricted,
12151186
None,
1187+
false,
12161188
ignore_binding,
12171189
ignore_import,
12181190
);
12191191

12201192
match result {
1221-
Err(ControlFlow::Break(Determined) | ControlFlow::Continue(Determined)) => continue,
1193+
Err(Determined) => continue,
12221194
Ok(binding)
12231195
if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) =>
12241196
{
12251197
continue;
12261198
}
1227-
Ok(_)
1228-
| Err(ControlFlow::Break(Undetermined) | ControlFlow::Continue(Undetermined)) => {
1229-
return Err(ControlFlow::Continue(Undetermined));
1230-
}
1199+
Ok(_) | Err(Undetermined) => return Err(ControlFlow::Continue(Undetermined)),
12311200
}
12321201
}
12331202

compiler/rustc_resolve/src/late.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ use tracing::{debug, instrument, trace};
4141

4242
use crate::{
4343
BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
44-
NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError,
45-
Used, errors, path_names_to_string, rustdoc,
44+
NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, Stage, TyCtxt,
45+
UseError, Used, errors, path_names_to_string, rustdoc,
4646
};
4747

4848
mod diagnostics;
@@ -1498,7 +1498,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14981498
opt_ns,
14991499
&self.parent_scope,
15001500
Some(source),
1501-
finalize,
1501+
finalize.map(|finalize| Finalize { stage: Stage::Late, ..finalize }),
15021502
Some(&self.ribs),
15031503
None,
15041504
None,

compiler/rustc_resolve/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ enum Scope<'ra> {
152152
enum ScopeSet<'ra> {
153153
/// All scopes with the given namespace.
154154
All(Namespace),
155+
/// Two scopes inside a module, for non-glob and glob bindings.
156+
Module(Namespace, Module<'ra>),
155157
/// A module, then extern prelude (used for mixed 2015-2018 mode in macros).
156158
ModuleAndExternPrelude(Namespace, Module<'ra>),
157159
/// Just two extern prelude scopes.

tests/ui/underscore-imports/shadow.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod b {
1414

1515
mod c {
1616
use crate::b::Shadow as _; // Only imports the struct
17+
//~^ ERROR `Shadow` is ambiguous
1718

1819
fn f(x: &()) {
1920
x.deref(); //~ ERROR no method named `deref` found
Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
1+
error[E0659]: `Shadow` is ambiguous
2+
--> $DIR/shadow.rs:16:19
3+
|
4+
LL | use crate::b::Shadow as _; // Only imports the struct
5+
| ^^^^^^ ambiguous name
6+
|
7+
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
8+
note: `Shadow` could refer to the struct defined here
9+
--> $DIR/shadow.rs:10:25
10+
|
11+
LL | ($i:ident) => { pub struct $i; }
12+
| ^^^^^^^^^^^^^^
13+
LL | }
14+
LL | m!(Shadow);
15+
| ---------- in this macro invocation
16+
= help: use `self::Shadow` to refer to this struct unambiguously
17+
note: `Shadow` could also refer to the trait imported here
18+
--> $DIR/shadow.rs:8:13
19+
|
20+
LL | pub use crate::a::*;
21+
| ^^^^^^^^^^^
22+
= help: use `self::Shadow` to refer to this trait unambiguously
23+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
24+
125
error[E0599]: no method named `deref` found for reference `&()` in the current scope
2-
--> $DIR/shadow.rs:19:11
26+
--> $DIR/shadow.rs:20:11
327
|
428
LL | x.deref();
529
| ^^^^^ method not found in `&()`
@@ -10,6 +34,7 @@ help: trait `Deref` which provides `deref` is implemented but not in scope; perh
1034
LL + use std::ops::Deref;
1135
|
1236

13-
error: aborting due to 1 previous error
37+
error: aborting due to 2 previous errors
1438

15-
For more information about this error, try `rustc --explain E0599`.
39+
Some errors have detailed explanations: E0599, E0659.
40+
For more information about an error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)