Skip to content

Commit 9c6a008

Browse files
committed
Auto merge of #31857 - jseyfried:fix_scoping, r=nikomatsakis
This fixes a bug (#31845) introduced in #31105 in which lexical scopes contain items from all anonymous module ancestors, even if the path to the anonymous module includes a normal module: ```rust fn f() { fn g() {} mod foo { fn h() { g(); // This erroneously resolves on nightly } } } ``` This is a [breaking-change] on nightly but not on stable or beta. r? @nikomatsakis
2 parents 15e9a95 + 2942cf7 commit 9c6a008

File tree

3 files changed

+56
-19
lines changed

3 files changed

+56
-19
lines changed

src/librustc_resolve/lib.rs

+27-19
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,8 @@ enum RibKind<'a> {
731731
// We're in a constant item. Can't refer to dynamic stuff.
732732
ConstantItemRibKind,
733733

734-
// We passed through an anonymous module.
735-
AnonymousModuleRibKind(Module<'a>),
734+
// We passed through a module.
735+
ModuleRibKind(Module<'a>),
736736
}
737737

738738
#[derive(Copy, Clone)]
@@ -1680,16 +1680,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16801680
fn with_scope<F>(&mut self, id: NodeId, f: F)
16811681
where F: FnOnce(&mut Resolver)
16821682
{
1683-
let orig_module = self.current_module;
1683+
if let Some(module) = self.current_module.module_children.borrow().get(&id) {
1684+
// Move down in the graph.
1685+
let orig_module = ::std::mem::replace(&mut self.current_module, module);
1686+
self.value_ribs.push(Rib::new(ModuleRibKind(module)));
1687+
self.type_ribs.push(Rib::new(ModuleRibKind(module)));
16841688

1685-
// Move down in the graph.
1686-
if let Some(module) = orig_module.module_children.borrow().get(&id) {
1687-
self.current_module = module;
1688-
}
1689+
f(self);
16891690

1690-
f(self);
1691-
1692-
self.current_module = orig_module;
1691+
self.current_module = orig_module;
1692+
self.value_ribs.pop();
1693+
self.type_ribs.pop();
1694+
} else {
1695+
f(self);
1696+
}
16931697
}
16941698

16951699
/// Searches the current set of local scopes for labels.
@@ -2266,8 +2270,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22662270

22672271
if let Some(anonymous_module) = anonymous_module {
22682272
debug!("(resolving block) found anonymous module, moving down");
2269-
self.value_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
2270-
self.type_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
2273+
self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
2274+
self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
22712275
self.current_module = anonymous_module;
22722276
} else {
22732277
self.value_ribs.push(Rib::new(NormalRibKind));
@@ -2811,8 +2815,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28112815
}
28122816

28132817
if check_ribs {
2814-
if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, namespace) {
2815-
return Some(def);
2818+
match self.resolve_identifier_in_local_ribs(identifier, namespace, record_used) {
2819+
Some(def) => return Some(def),
2820+
None => {}
28162821
}
28172822
}
28182823

@@ -2844,7 +2849,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28442849
Def::Local(_, node_id) => {
28452850
for rib in ribs {
28462851
match rib.kind {
2847-
NormalRibKind | AnonymousModuleRibKind(..) => {
2852+
NormalRibKind | ModuleRibKind(..) => {
28482853
// Nothing to do. Continue.
28492854
}
28502855
ClosureRibKind(function_id) => {
@@ -2893,7 +2898,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28932898
for rib in ribs {
28942899
match rib.kind {
28952900
NormalRibKind | MethodRibKind | ClosureRibKind(..) |
2896-
AnonymousModuleRibKind(..) => {
2901+
ModuleRibKind(..) => {
28972902
// Nothing to do. Continue.
28982903
}
28992904
ItemRibKind => {
@@ -3024,7 +3029,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30243029

30253030
fn resolve_identifier_in_local_ribs(&mut self,
30263031
ident: hir::Ident,
3027-
namespace: Namespace)
3032+
namespace: Namespace,
3033+
record_used: bool)
30283034
-> Option<LocalDef> {
30293035
// Check the local set of ribs.
30303036
let name = match namespace { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
@@ -3051,16 +3057,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30513057
}
30523058
}
30533059

3054-
if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
3060+
if let ModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
30553061
if let Success(binding) = self.resolve_name_in_module(module,
30563062
ident.unhygienic_name,
30573063
namespace,
30583064
true,
3059-
true) {
3065+
record_used) {
30603066
if let Some(def) = binding.def() {
30613067
return Some(LocalDef::from_def(def));
30623068
}
30633069
}
3070+
// We can only see through anonymous modules
3071+
if module.def.is_some() { return None; }
30643072
}
30653073
}
30663074

src/test/compile-fail/issue-31845.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Checks lexical scopes cannot see through normal module boundries
12+
13+
fn f() {
14+
fn g() {}
15+
mod foo {
16+
fn h() {
17+
g(); //~ ERROR unresolved name
18+
}
19+
}
20+
}
21+
22+
fn main() {}

src/test/compile-fail/lint-unused-imports.rs

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ mod bar {
6969
}
7070
}
7171

72+
fn g() {
73+
use self::g; //~ ERROR unused import
74+
fn f() {
75+
self::g();
76+
}
77+
}
78+
7279
fn main() {
7380
cal(foo::Point{x:3, y:9});
7481
let mut a = 3;

0 commit comments

Comments
 (0)