Skip to content

Commit 83d2c0b

Browse files
committed
rustc: Disallow importing through use statements
Resolve is currently erroneously allowing imports through private `use` statements in some circumstances, even across module boundaries. For example, this code compiles successfully today: use std::c_str; mod test { use c_str::CString; } This should not be allowed because it was explicitly decided that private `use` statements are purely bringing local names into scope, they are not participating further in name resolution. As a consequence of this patch, this code, while valid today, is now invalid: mod test { use std::c_str; unsafe fn foo() { ::test::c_str::CString::new(0 as *u8, false); } } While plausibly acceptable, I found it to be more consistent if private imports were only considered candidates to resolve the first component in a path, and no others. Closes #12612
1 parent 0bf4e90 commit 83d2c0b

File tree

8 files changed

+101
-18
lines changed

8 files changed

+101
-18
lines changed

Diff for: src/libnative/io/file_win32.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ pub fn mkdir(p: &CString, _mode: io::FilePermission) -> IoResult<()> {
324324
}
325325

326326
pub fn readdir(p: &CString) -> IoResult<Vec<Path>> {
327-
use rt::global_heap::malloc_raw;
327+
use std::rt::global_heap::malloc_raw;
328328

329329
fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
330330
let root = unsafe { CString::new(root.with_ref(|p| p), false) };

Diff for: src/librustc/front/test.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -297,20 +297,22 @@ mod __test {
297297

298298
fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
299299
let id_test = token::str_to_ident("test");
300-
let vi = if cx.is_test_crate {
301-
ast::ViewItemUse(
300+
let (vi, vis) = if cx.is_test_crate {
301+
(ast::ViewItemUse(
302302
vec!(@nospan(ast::ViewPathSimple(id_test,
303303
path_node(vec!(id_test)),
304-
ast::DUMMY_NODE_ID))))
304+
ast::DUMMY_NODE_ID)))),
305+
ast::Public)
305306
} else {
306-
ast::ViewItemExternCrate(id_test,
307+
(ast::ViewItemExternCrate(id_test,
307308
with_version("test"),
308-
ast::DUMMY_NODE_ID)
309+
ast::DUMMY_NODE_ID),
310+
ast::Inherited)
309311
};
310312
ast::ViewItem {
311313
node: vi,
312314
attrs: Vec::new(),
313-
vis: ast::Inherited,
315+
vis: vis,
314316
span: DUMMY_SP
315317
}
316318
}

Diff for: src/librustc/middle/resolve.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -2286,10 +2286,12 @@ impl<'a> Resolver<'a> {
22862286
}
22872287
Some(child_name_bindings) => {
22882288
if child_name_bindings.defined_in_namespace(ValueNS) {
2289+
debug!("(resolving single import) found value binding");
22892290
value_result = BoundResult(containing_module,
22902291
*child_name_bindings);
22912292
}
22922293
if child_name_bindings.defined_in_namespace(TypeNS) {
2294+
debug!("(resolving single import) found type binding");
22932295
type_result = BoundResult(containing_module,
22942296
*child_name_bindings);
22952297
}
@@ -2320,6 +2322,7 @@ impl<'a> Resolver<'a> {
23202322
.borrow();
23212323
match import_resolutions.find(&source.name) {
23222324
None => {
2325+
debug!("(resolving single import) no import");
23232326
// The containing module definitely doesn't have an
23242327
// exported import with the name in question. We can
23252328
// therefore accurately report that the names are
@@ -2353,6 +2356,8 @@ impl<'a> Resolver<'a> {
23532356
return UnboundResult;
23542357
}
23552358
Some(target) => {
2359+
debug!("(resolving single import) found \
2360+
import in ns {:?}", namespace);
23562361
let id = import_resolution.id(namespace);
23572362
this.used_imports.insert((id, namespace));
23582363
return BoundResult(target.target_module,
@@ -2396,6 +2401,8 @@ impl<'a> Resolver<'a> {
23962401
.find_copy(&source.name) {
23972402
None => {} // Continue.
23982403
Some(module) => {
2404+
debug!("(resolving single import) found external \
2405+
module");
23992406
let name_bindings =
24002407
@Resolver::create_name_bindings_from_module(
24012408
module);
@@ -2669,7 +2676,8 @@ impl<'a> Resolver<'a> {
26692676
match self.resolve_name_in_module(search_module,
26702677
name,
26712678
TypeNS,
2672-
name_search_type) {
2679+
name_search_type,
2680+
false) {
26732681
Failed => {
26742682
let segment_name = token::get_ident(name);
26752683
let module_name = self.module_to_str(search_module);
@@ -2977,7 +2985,8 @@ impl<'a> Resolver<'a> {
29772985
match self.resolve_name_in_module(search_module,
29782986
name,
29792987
namespace,
2980-
PathSearch) {
2988+
PathSearch,
2989+
true) {
29812990
Failed => {
29822991
// Continue up the search chain.
29832992
}
@@ -3141,7 +3150,8 @@ impl<'a> Resolver<'a> {
31413150
module_: @Module,
31423151
name: Ident,
31433152
namespace: Namespace,
3144-
name_search_type: NameSearchType)
3153+
name_search_type: NameSearchType,
3154+
allow_private_imports: bool)
31453155
-> ResolveResult<(Target, bool)> {
31463156
debug!("(resolving name in module) resolving `{}` in `{}`",
31473157
token::get_ident(name),
@@ -3172,7 +3182,9 @@ impl<'a> Resolver<'a> {
31723182

31733183
// Check the list of resolved imports.
31743184
match module_.import_resolutions.borrow().find(&name.name) {
3175-
Some(import_resolution) => {
3185+
Some(import_resolution) if allow_private_imports ||
3186+
import_resolution.is_public.get() => {
3187+
31763188
if import_resolution.is_public.get() &&
31773189
import_resolution.outstanding_references.get() != 0 {
31783190
debug!("(resolving name in module) import \
@@ -3193,7 +3205,7 @@ impl<'a> Resolver<'a> {
31933205
}
31943206
}
31953207
}
3196-
None => {} // Continue.
3208+
Some(..) | None => {} // Continue.
31973209
}
31983210

31993211
// Finally, search through external children.

Diff for: src/test/auxiliary/issue-12612-1.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2014 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+
pub mod bar {
12+
pub fn foo() {}
13+
}

Diff for: src/test/auxiliary/issue-12612-2.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2014 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+
pub fn baz() {}

Diff for: src/test/compile-fail/issue-12612.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2014 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+
// aux-build:issue-12612-1.rs
12+
13+
extern crate foo = "issue-12612-1";
14+
15+
use foo::bar;
16+
17+
mod test {
18+
use bar::foo;
19+
//~^ ERROR: unresolved import
20+
//~^^ ERROR: failed to resolve import
21+
}
22+
23+
fn main() {}
24+

Diff for: src/test/run-pass/issue-11881.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
extern crate ser = "serialize";
11+
extern crate serialize;
1212

13-
use serialize = self::ser;
14-
//necessary for deriving(Encodable)
15-
use ser::{Encodable, Encoder};
16-
use ser::json;
17-
use ser::ebml::writer;
13+
use serialize::{Encodable, Encoder};
14+
use serialize::json;
15+
use serialize::ebml::writer;
1816
use std::io::MemWriter;
1917
use std::str::from_utf8_owned;
2018

Diff for: src/test/run-pass/issue-12612.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2014 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+
// aux-build:issue-12612-1.rs
12+
// aux-build:issue-12612-2.rs
13+
14+
extern crate foo = "issue-12612-1";
15+
extern crate bar = "issue-12612-2";
16+
17+
use foo::bar;
18+
19+
mod test {
20+
use bar::baz;
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)