Skip to content

Commit 797ef60

Browse files
committed
resolve: allow super in module in block to refer to block items
1 parent 8e863eb commit 797ef60

File tree

6 files changed

+335
-12
lines changed

6 files changed

+335
-12
lines changed

compiler/rustc_resolve/src/imports.rs

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use crate::diagnostics::Suggestion;
44
use crate::Determinacy::{self, *};
55
use crate::Namespace::{self, MacroNS, TypeNS};
66
use crate::{module_to_string, names_to_string};
7+
use crate::{AllowResolveBlocks, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
78
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
8-
use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
99
use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak};
10-
use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
10+
use crate::{ModuleData, NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
1111

1212
use rustc_ast::unwrap_or;
1313
use rustc_ast::NodeId;
@@ -777,13 +777,15 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
777777
// For better failure detection, pretend that the import will
778778
// not define any names while resolving its module path.
779779
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
780-
let path_res = self.r.resolve_path(
780+
let path_res = self.r.resolve_path_with_ribs(
781781
&import.module_path,
782782
None,
783783
&import.parent_scope,
784784
false,
785785
import.span,
786786
import.crate_lint(),
787+
None,
788+
AllowResolveBlocks::Yes,
787789
);
788790
import.vis.set(orig_vis);
789791

@@ -818,16 +820,37 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
818820
// For better failure detection, pretend that the import will
819821
// not define any names while resolving its module path.
820822
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
821-
let binding = this.resolve_ident_in_module(
823+
let mut binding = this.resolve_ident_in_module(
822824
module,
823825
source,
824826
ns,
825827
&import.parent_scope,
826828
false,
827829
import.span,
828830
);
829-
import.vis.set(orig_vis);
830831

832+
let mut module = module;
833+
while binding.is_err() {
834+
match module {
835+
ModuleOrUniformRoot::Module(m @ ModuleData { parent: Some(p), .. })
836+
if m.is_block() =>
837+
{
838+
// item not found in opaque block module; try inside module containing the block
839+
module = ModuleOrUniformRoot::Module(*p);
840+
binding = this.resolve_ident_in_module(
841+
module,
842+
source,
843+
ns,
844+
&import.parent_scope,
845+
false,
846+
import.span,
847+
);
848+
}
849+
_ => break,
850+
}
851+
}
852+
853+
import.vis.set(orig_vis);
831854
source_bindings[ns].set(binding);
832855
} else {
833856
return;
@@ -878,13 +901,15 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
878901
_ => None,
879902
};
880903
let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
881-
let path_res = self.r.resolve_path(
904+
let path_res = self.r.resolve_path_with_ribs(
882905
&import.module_path,
883906
None,
884907
&import.parent_scope,
885908
true,
886909
import.span,
887910
import.crate_lint(),
911+
None,
912+
AllowResolveBlocks::Yes,
888913
);
889914
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
890915
if let Some(orig_unusable_binding) = orig_unusable_binding {
@@ -1010,14 +1035,36 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
10101035
let orig_unusable_binding =
10111036
mem::replace(&mut this.unusable_binding, target_bindings[ns].get());
10121037
let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
1013-
let binding = this.resolve_ident_in_module(
1038+
let mut binding = this.resolve_ident_in_module(
10141039
module,
10151040
ident,
10161041
ns,
10171042
&import.parent_scope,
10181043
true,
10191044
import.span,
10201045
);
1046+
1047+
let mut module = module;
1048+
while binding.is_err() {
1049+
match module {
1050+
ModuleOrUniformRoot::Module(m @ ModuleData { parent: Some(p), .. })
1051+
if m.is_block() =>
1052+
{
1053+
// item not found in opaque block module; try inside module containing the block
1054+
module = ModuleOrUniformRoot::Module(*p);
1055+
binding = this.resolve_ident_in_module(
1056+
module,
1057+
ident,
1058+
ns,
1059+
&import.parent_scope,
1060+
false,
1061+
import.span,
1062+
);
1063+
}
1064+
_ => break,
1065+
}
1066+
}
1067+
10211068
this.last_import_segment = orig_last_import_segment;
10221069
this.unusable_binding = orig_unusable_binding;
10231070
import.vis.set(orig_vis);
@@ -1323,7 +1370,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13231370
}
13241371

13251372
fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
1326-
let module = match import.imported_module.get().unwrap() {
1373+
let mut module = match import.imported_module.get().unwrap() {
13271374
ModuleOrUniformRoot::Module(module) => module,
13281375
_ => {
13291376
self.r.session.span_err(import.span, "cannot glob-import all possible crates");
@@ -1346,7 +1393,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13461393

13471394
// Ensure that `resolutions` isn't borrowed during `try_define`,
13481395
// since it might get updated via a glob cycle.
1349-
let bindings = self
1396+
let mut bindings = self
13501397
.r
13511398
.resolutions(module)
13521399
.borrow()
@@ -1355,6 +1402,53 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13551402
resolution.borrow().binding().map(|binding| (*key, binding))
13561403
})
13571404
.collect::<Vec<_>>();
1405+
1406+
if module.is_block() {
1407+
// Glob imports should see "through" an opaque module.
1408+
// Prefer items in the opaque module to items in the parent.
1409+
1410+
let mut imported_items = FxHashSet::default();
1411+
1412+
while module.is_block() && module.parent.is_some() {
1413+
// import these bindings
1414+
for (mut key, binding) in bindings {
1415+
let scope =
1416+
match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
1417+
Some(Some(def)) => self.r.macro_def_scope(def),
1418+
Some(None) => import.parent_scope.module,
1419+
None => continue,
1420+
};
1421+
if self.r.is_accessible_from(binding.vis, scope) {
1422+
let imported_binding = self.r.import(binding, import);
1423+
let _ =
1424+
self.r.try_define(import.parent_scope.module, key, imported_binding);
1425+
imported_items.insert(key);
1426+
}
1427+
}
1428+
1429+
// This was an opaque module; repeat with parent module.
1430+
module = module.parent.unwrap();
1431+
1432+
// Add to module's glob_importers
1433+
module.glob_importers.borrow_mut().push(import);
1434+
1435+
// Ensure that `resolutions` isn't borrowed during `try_define`,
1436+
// since it might get updated via a glob cycle.
1437+
bindings = self
1438+
.r
1439+
.resolutions(module)
1440+
.borrow()
1441+
.iter()
1442+
.filter_map(|(key, resolution)| {
1443+
if imported_items.contains(key) {
1444+
return None;
1445+
}
1446+
resolution.borrow().binding().map(|binding| (*key, binding))
1447+
})
1448+
.collect::<Vec<_>>();
1449+
}
1450+
}
1451+
13581452
for (mut key, binding) in bindings {
13591453
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
13601454
Some(Some(def)) => self.r.macro_def_scope(def),

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
747747
path_span,
748748
crate_lint,
749749
Some(&self.ribs),
750+
crate::AllowResolveBlocks::No,
750751
)
751752
}
752753

compiler/rustc_resolve/src/lib.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#![feature(box_patterns)]
1313
#![feature(bool_to_option)]
1414
#![feature(control_flow_enum)]
15+
#![feature(bindings_after_at)]
1516
#![feature(crate_visibility_modifier)]
1617
#![feature(format_args_capture)]
1718
#![feature(nll)]
@@ -597,6 +598,10 @@ impl<'a> ModuleData<'a> {
597598
matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _))
598599
}
599600

601+
fn is_block(&self) -> bool {
602+
matches!(self.kind, ModuleKind::Block(_))
603+
}
604+
600605
fn nearest_item_scope(&'a self) -> Module<'a> {
601606
match self.kind {
602607
ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => {
@@ -839,6 +844,13 @@ enum BuiltinMacroState {
839844
AlreadySeen(Span),
840845
}
841846

847+
/// Whether resolve_path_with_ribs may resolve to anonymous block modules
848+
#[derive(Copy, Clone, Debug)]
849+
enum AllowResolveBlocks {
850+
No,
851+
Yes,
852+
}
853+
842854
/// The main resolver class.
843855
///
844856
/// This is the visitor that walks the whole crate.
@@ -2177,6 +2189,7 @@ impl<'a> Resolver<'a> {
21772189
path_span,
21782190
crate_lint,
21792191
None,
2192+
AllowResolveBlocks::No,
21802193
)
21812194
}
21822195

@@ -2189,6 +2202,7 @@ impl<'a> Resolver<'a> {
21892202
path_span: Span,
21902203
crate_lint: CrateLint,
21912204
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
2205+
resolve_opaque: AllowResolveBlocks,
21922206
) -> PathResult<'a> {
21932207
let mut module = None;
21942208
let mut allow_super = true;
@@ -2231,9 +2245,11 @@ impl<'a> Resolver<'a> {
22312245
};
22322246
if let Some(self_module) = self_module {
22332247
if let Some(parent) = self_module.parent {
2234-
module = Some(ModuleOrUniformRoot::Module(
2235-
self.resolve_self(&mut ctxt, parent),
2236-
));
2248+
let resolved = match (resolve_opaque, &parent.kind) {
2249+
(AllowResolveBlocks::Yes, ModuleKind::Block(_)) => parent,
2250+
_ => self.resolve_self(&mut ctxt, parent),
2251+
};
2252+
module = Some(ModuleOrUniformRoot::Module(resolved));
22372253
continue;
22382254
}
22392255
}

src/test/rustdoc/mod-in-doctest.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// compile-flags:--test
2+
// edition:2018
3+
4+
//! ```
5+
//! fn foo() {}
6+
//!
7+
//! mod bar {
8+
//! use super::foo;
9+
//! fn bar() {
10+
//! foo()
11+
//! }
12+
//! }
13+
//! ```
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// build-pass
2+
3+
const CONST: &str = "OUTER";
4+
fn bar() -> &'static str { "outer" }
5+
6+
fn module_in_function_use_super() {
7+
mod inner {
8+
use super::{bar, CONST};
9+
fn call_bar() {
10+
bar();
11+
}
12+
13+
fn get_const() -> &'static str {
14+
CONST
15+
}
16+
}
17+
}
18+
19+
fn module_in_function_resolve_super() {
20+
mod inner {
21+
fn call_bar() {
22+
super::bar();
23+
}
24+
25+
fn get_const() -> &'static str {
26+
super::CONST
27+
}
28+
}
29+
}
30+
31+
32+
fn module_in_function_use_super_glob() {
33+
mod inner {
34+
use super::*;
35+
fn call_bar() {
36+
bar();
37+
}
38+
39+
fn get_const() -> &'static str {
40+
CONST
41+
}
42+
}
43+
}
44+
45+
fn module_in_block_use_super() {
46+
{
47+
mod inner {
48+
use super::{bar, CONST};
49+
fn call_bar() {
50+
bar();
51+
}
52+
53+
fn get_const() -> &'static str {
54+
CONST
55+
}
56+
}
57+
}
58+
}
59+
60+
fn module_in_block_resolve_super() {
61+
{
62+
mod inner {
63+
fn call_bar() {
64+
super::bar();
65+
}
66+
67+
fn get_const() -> &'static str {
68+
super::CONST
69+
}
70+
}
71+
}
72+
}
73+
74+
75+
fn module_in_block_use_super_glob() {
76+
{
77+
mod inner {
78+
use super::*;
79+
fn call_bar() {
80+
bar();
81+
}
82+
83+
fn get_const() -> &'static str {
84+
CONST
85+
}
86+
}
87+
}
88+
}
89+
90+
fn main() {
91+
module_in_function_use_super();
92+
module_in_function_resolve_super();
93+
module_in_function_use_super_glob();
94+
95+
module_in_block_use_super();
96+
module_in_block_resolve_super();
97+
module_in_block_use_super_glob();
98+
}

0 commit comments

Comments
 (0)