Skip to content

Commit c1492fe

Browse files
committed
Add one more prelude layer for extern crate names passed with --extern
1 parent 7f3444e commit c1492fe

13 files changed

+204
-8
lines changed

src/librustc_resolve/lib.rs

+29-7
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,32 @@ 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+
// `record_used` means that we don't try to load crates during speculative resolution
1977+
if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
1978+
if !self.session.features_untracked().extern_prelude {
1979+
feature_err(&self.session.parse_sess, "extern_prelude",
1980+
ident.span, GateIssue::Language,
1981+
"access to extern crates through prelude is experimental").emit();
1982+
}
1983+
1984+
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
1985+
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
1986+
self.populate_module_if_necessary(crate_root);
1987+
1988+
let binding = (crate_root, ty::Visibility::Public,
1989+
ident.span, Mark::root()).to_name_binding(self.arenas);
1990+
return Some(LexicalScopeBinding::Item(binding));
1991+
}
1992+
if let Some(prelude) = self.prelude {
1993+
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
1994+
false, false, path_span) {
1995+
return Some(LexicalScopeBinding::Item(binding));
1996+
}
19771997
}
1978-
_ => None,
19791998
}
1999+
2000+
None
19802001
}
19812002

19822003
fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
@@ -3587,8 +3608,9 @@ impl<'a> Resolver<'a> {
35873608
// We can see through blocks
35883609
} else {
35893610
// Items from the prelude
3590-
if let Some(prelude) = self.prelude {
3591-
if !module.no_implicit_prelude {
3611+
if !module.no_implicit_prelude {
3612+
names.extend(self.extern_prelude.iter().cloned());
3613+
if let Some(prelude) = self.prelude {
35923614
add_module_candidates(prelude, &mut names);
35933615
}
35943616
}

src/libsyntax/feature_gate.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ declare_features! (
397397
(active, generic_associated_types, "1.23.0", Some(44265), None),
398398

399399
// Resolve absolute paths as paths from other crates
400-
(active, extern_absolute_paths, "1.24.0", Some(44660), None),
400+
(active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)),
401401

402402
// `foo.rs` as an alternative to `foo/mod.rs`
403403
(active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
@@ -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), Some(Edition::Edition2018)),
469472
);
470473

471474
declare_features! (
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"
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+
}
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+
}
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: ()) {}
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+
}
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+
}
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+
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere
12+
13+
mod m {
14+
pub struct LooksLikeExternCrate;
15+
}
16+
17+
fn main() {
18+
// OK, speculative resolution for `unused_qualifications` doesn't try
19+
// to resolve this as an extern crate and load that crate
20+
let s = m::LooksLikeExternCrate {};
21+
}
+11
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 `-`
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)