Add one more prelude layer for extern crate names passed with --extern

This commit is contained in:
Vadim Petrochenkov 2018-04-08 15:34:35 +03:00
parent 7f3444e1ba
commit c1492fe303
13 changed files with 204 additions and 8 deletions

View File

@ -1407,6 +1407,7 @@ pub struct Resolver<'a> {
graph_root: Module<'a>,
prelude: Option<Module<'a>>,
extern_prelude: FxHashSet<Name>,
/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
@ -1715,6 +1716,7 @@ impl<'a> Resolver<'a> {
// AST.
graph_root,
prelude: None,
extern_prelude: session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(),
has_self: FxHashSet(),
field_names: FxHashMap(),
@ -1970,13 +1972,32 @@ impl<'a> Resolver<'a> {
}
}
match self.prelude {
Some(prelude) if !module.no_implicit_prelude => {
self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span)
.ok().map(LexicalScopeBinding::Item)
if !module.no_implicit_prelude {
// `record_used` means that we don't try to load crates during speculative resolution
if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
if !self.session.features_untracked().extern_prelude {
feature_err(&self.session.parse_sess, "extern_prelude",
ident.span, GateIssue::Language,
"access to extern crates through prelude is experimental").emit();
}
_ => None,
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
let binding = (crate_root, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas);
return Some(LexicalScopeBinding::Item(binding));
}
if let Some(prelude) = self.prelude {
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
false, false, path_span) {
return Some(LexicalScopeBinding::Item(binding));
}
}
}
None
}
fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
@ -3587,8 +3608,9 @@ impl<'a> Resolver<'a> {
// We can see through blocks
} else {
// Items from the prelude
if let Some(prelude) = self.prelude {
if !module.no_implicit_prelude {
names.extend(self.extern_prelude.iter().cloned());
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
}

View File

@ -397,7 +397,7 @@ declare_features! (
(active, generic_associated_types, "1.23.0", Some(44265), None),
// Resolve absolute paths as paths from other crates
(active, extern_absolute_paths, "1.24.0", Some(44660), None),
(active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)),
// `foo.rs` as an alternative to `foo/mod.rs`
(active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
@ -466,6 +466,9 @@ declare_features! (
// #[doc(alias = "...")]
(active, doc_alias, "1.27.0", Some(50146), None),
// Access to crate names passed via `--extern` through prelude
(active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)),
);
declare_features! (

View File

@ -0,0 +1,12 @@
-include ../tools.mk
all:
$(RUSTC) ep-lib.rs
$(RUSTC) ep-vec.rs
$(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
$(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
$(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
$(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental"
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"

View File

@ -0,0 +1,16 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(extern_prelude)]
fn main() {
let s = ep_lib::S; // It works
s.external();
}

View File

@ -0,0 +1,17 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "rlib"]
pub struct S;
impl S {
pub fn external(&self) {}
}

View File

@ -0,0 +1,13 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "rlib"]
pub fn new(arg1: f32, arg2: ()) {}

View File

@ -0,0 +1,13 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let s = ep_lib::S; // Feature error
}

View File

@ -0,0 +1,19 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Extern prelude names are not available by absolute paths
#![feature(extern_prelude)]
use ep_lib::S;
fn main() {
let s = ::ep_lib::S;
}

View File

@ -0,0 +1,24 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Local module shadows `ep_lib` from extern prelude
mod ep_lib {
pub struct S;
impl S {
pub fn internal(&self) {}
}
}
fn main() {
let s = ep_lib::S;
s.internal(); // OK
}

View File

@ -0,0 +1,17 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Extern prelude shadows standard library prelude
#![feature(extern_prelude)]
fn main() {
let x = Vec::new(0f32, ()); // OK
}

View File

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere
mod m {
pub struct LooksLikeExternCrate;
}
fn main() {
// OK, speculative resolution for `unused_qualifications` doesn't try
// to resolve this as an extern crate and load that crate
let s = m::LooksLikeExternCrate {};
}

View File

@ -0,0 +1,11 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`

View File

@ -0,0 +1,8 @@
error: expected one of `!` or `::`, found `-`
--> $DIR/feature-gate-extern_prelude.rs:11:4
|
LL | can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
| ^ expected one of `!` or `::` here
error: aborting due to previous error