Skip to content

Commit 2ec6fac

Browse files
petrochenkovManishearth
authored andcommitted
Add one more prelude layer for extern crate names passed with --extern
1 parent 25749ad commit 2ec6fac

File tree

12 files changed

+181
-7
lines changed

12 files changed

+181
-7
lines changed

src/librustc_resolve/lib.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,7 @@ pub struct Resolver<'a> {
14071407
graph_root: Module<'a>,
14081408

14091409
prelude: Option<Module<'a>>,
1410+
extern_prelude: FxHashSet<Name>,
14101411

14111412
/// n.b. This is used only for better diagnostics, not name resolution itself.
14121413
has_self: FxHashSet<DefId>,
@@ -1715,6 +1716,7 @@ impl<'a> Resolver<'a> {
17151716
// AST.
17161717
graph_root,
17171718
prelude: None,
1719+
extern_prelude: session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(),
17181720

17191721
has_self: FxHashSet(),
17201722
field_names: FxHashMap(),
@@ -1970,13 +1972,31 @@ impl<'a> Resolver<'a> {
19701972
}
19711973
}
19721974

1973-
match self.prelude {
1974-
Some(prelude) if !module.no_implicit_prelude => {
1975-
self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span)
1976-
.ok().map(LexicalScopeBinding::Item)
1975+
if !module.no_implicit_prelude {
1976+
if ns == TypeNS && self.extern_prelude.contains(&ident.name) {
1977+
if !self.session.features_untracked().extern_prelude {
1978+
feature_err(&self.session.parse_sess, "extern_prelude",
1979+
ident.span, GateIssue::Language,
1980+
"access to extern crates through prelude is experimental").emit();
1981+
}
1982+
1983+
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
1984+
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
1985+
self.populate_module_if_necessary(crate_root);
1986+
1987+
let binding = (crate_root, ty::Visibility::Public,
1988+
ident.span, Mark::root()).to_name_binding(self.arenas);
1989+
return Some(LexicalScopeBinding::Item(binding));
1990+
}
1991+
if let Some(prelude) = self.prelude {
1992+
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
1993+
false, false, path_span) {
1994+
return Some(LexicalScopeBinding::Item(binding));
1995+
}
19771996
}
1978-
_ => None,
19791997
}
1998+
1999+
None
19802000
}
19812001

19822002
fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
@@ -3586,8 +3606,9 @@ impl<'a> Resolver<'a> {
35863606
// We can see through blocks
35873607
} else {
35883608
// Items from the prelude
3589-
if let Some(prelude) = self.prelude {
3590-
if !module.no_implicit_prelude {
3609+
if !module.no_implicit_prelude {
3610+
names.extend(self.extern_prelude.iter().cloned());
3611+
if let Some(prelude) = self.prelude {
35913612
add_module_candidates(prelude, &mut names);
35923613
}
35933614
}

src/libsyntax/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ declare_features! (
466466

467467
// #[doc(alias = "...")]
468468
(active, doc_alias, "1.27.0", Some(50146), None),
469+
470+
// Access to crate names passed via `--extern` through prelude
471+
(active, extern_prelude, "1.27.0", Some(44660), None),
469472
);
470473

471474
declare_features! (
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(RUSTC) ep-lib.rs
5+
$(RUSTC) ep-vec.rs
6+
7+
$(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
8+
$(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
9+
$(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
10+
$(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental"
11+
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
12+
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 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+
#![feature(extern_prelude)]
12+
13+
fn main() {
14+
let s = ep_lib::S; // It works
15+
s.external();
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2017 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+
#![crate_type = "rlib"]
12+
13+
pub struct S;
14+
15+
impl S {
16+
pub fn external(&self) {}
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2017 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+
#![crate_type = "rlib"]
12+
13+
pub fn new(arg1: f32, arg2: ()) {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2018 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+
fn main() {
12+
let s = ep_lib::S; // Feature error
13+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2018 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+
// Extern prelude names are not available by absolute paths
12+
13+
#![feature(extern_prelude)]
14+
15+
use ep_lib::S;
16+
17+
fn main() {
18+
let s = ::ep_lib::S;
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2018 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+
// Local module shadows `ep_lib` from extern prelude
12+
13+
mod ep_lib {
14+
pub struct S;
15+
16+
impl S {
17+
pub fn internal(&self) {}
18+
}
19+
}
20+
21+
fn main() {
22+
let s = ep_lib::S;
23+
s.internal(); // OK
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2018 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+
// Extern prelude shadows standard library prelude
12+
13+
#![feature(extern_prelude)]
14+
15+
fn main() {
16+
let x = Vec::new(0f32, ()); // OK
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2018 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+
can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected one of `!` or `::`, found `-`
2+
--> $DIR/feature-gate-extern_prelude.rs:11:4
3+
|
4+
LL | can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
5+
| ^ expected one of `!` or `::` here
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)