rustc_resolve: always include core, std and meta in the extern prelude.

This commit is contained in:
Eduard-Mihai Burtescu 2018-09-10 19:41:30 +03:00
parent 9eb7a3c76f
commit 38c82a2180
9 changed files with 181 additions and 45 deletions

View File

@ -100,6 +100,18 @@ enum LoadResult {
Loaded(Library), Loaded(Library),
} }
enum LoadError<'a> {
LocatorError(locator::Context<'a>),
}
impl<'a> LoadError<'a> {
fn report(self) -> ! {
match self {
LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(),
}
}
}
impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> {
pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
CrateLoader { CrateLoader {
@ -268,16 +280,17 @@ impl<'a> CrateLoader<'a> {
(cnum, cmeta) (cnum, cmeta)
} }
fn resolve_crate(&mut self, fn resolve_crate<'b>(
root: &Option<CratePaths>, &'b mut self,
ident: Symbol, root: &'b Option<CratePaths>,
name: Symbol, ident: Symbol,
hash: Option<&Svh>, name: Symbol,
extra_filename: Option<&str>, hash: Option<&'b Svh>,
span: Span, extra_filename: Option<&'b str>,
path_kind: PathKind, span: Span,
mut dep_kind: DepKind) path_kind: PathKind,
-> (CrateNum, Lrc<cstore::CrateMetadata>) { mut dep_kind: DepKind,
) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
info!("resolving crate `extern crate {} as {}`", name, ident); info!("resolving crate `extern crate {} as {}`", name, ident);
let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
LoadResult::Previous(cnum) LoadResult::Previous(cnum)
@ -321,7 +334,7 @@ impl<'a> CrateLoader<'a> {
}; };
self.load(&mut proc_macro_locator) self.load(&mut proc_macro_locator)
}).unwrap_or_else(|| locate_ctxt.report_errs()) }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
}; };
match result { match result {
@ -333,10 +346,10 @@ impl<'a> CrateLoader<'a> {
data.dep_kind.with_lock(|data_dep_kind| { data.dep_kind.with_lock(|data_dep_kind| {
*data_dep_kind = cmp::max(*data_dep_kind, dep_kind); *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
}); });
(cnum, data) Ok((cnum, data))
} }
LoadResult::Loaded(library) => { LoadResult::Loaded(library) => {
self.register_crate(root, ident, span, library, dep_kind) Ok(self.register_crate(root, ident, span, library, dep_kind))
} }
} }
} }
@ -441,7 +454,7 @@ impl<'a> CrateLoader<'a> {
let (local_cnum, ..) = self.resolve_crate( let (local_cnum, ..) = self.resolve_crate(
root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span,
PathKind::Dependency, dep_kind, PathKind::Dependency, dep_kind,
); ).unwrap_or_else(|err| err.report());
local_cnum local_cnum
})).collect() })).collect()
} }
@ -695,7 +708,8 @@ impl<'a> CrateLoader<'a> {
let dep_kind = DepKind::Implicit; let dep_kind = DepKind::Implicit;
let (cnum, data) = let (cnum, data) =
self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind)
.unwrap_or_else(|err| err.report());
// Sanity check the loaded crate to ensure it is indeed a panic runtime // Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was. // and the panic strategy is indeed what we thought it was.
@ -803,7 +817,8 @@ impl<'a> CrateLoader<'a> {
let dep_kind = DepKind::Explicit; let dep_kind = DepKind::Explicit;
let (_, data) = let (_, data) =
self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
PathKind::Crate, dep_kind); PathKind::Crate, dep_kind)
.unwrap_or_else(|err| err.report());
// Sanity check the loaded crate to ensure it is indeed a sanitizer runtime // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
if !data.root.sanitizer_runtime { if !data.root.sanitizer_runtime {
@ -826,7 +841,8 @@ impl<'a> CrateLoader<'a> {
let dep_kind = DepKind::Implicit; let dep_kind = DepKind::Implicit;
let (_, data) = let (_, data) =
self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
PathKind::Crate, dep_kind); PathKind::Crate, dep_kind)
.unwrap_or_else(|err| err.report());
// Sanity check the loaded crate to ensure it is indeed a profiler runtime // Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.root.profiler_runtime { if !data.root.profiler_runtime {
@ -946,7 +962,8 @@ impl<'a> CrateLoader<'a> {
None, None,
DUMMY_SP, DUMMY_SP,
PathKind::Crate, PathKind::Crate,
DepKind::Implicit); DepKind::Implicit)
.unwrap_or_else(|err| err.report());
self.sess.injected_allocator.set(Some(cnum)); self.sess.injected_allocator.set(Some(cnum));
data data
}) })
@ -1103,7 +1120,7 @@ impl<'a> CrateLoader<'a> {
let (cnum, ..) = self.resolve_crate( let (cnum, ..) = self.resolve_crate(
&None, item.ident.name, orig_name, None, None, &None, item.ident.name, orig_name, None, None,
item.span, PathKind::Crate, dep_kind, item.span, PathKind::Crate, dep_kind,
); ).unwrap_or_else(|err| err.report());
let def_id = definitions.opt_local_def_id(item.id).unwrap(); let def_id = definitions.opt_local_def_id(item.id).unwrap();
let path_len = definitions.def_path(def_id.index).data.len(); let path_len = definitions.def_path(def_id.index).data.len();
@ -1131,7 +1148,7 @@ impl<'a> CrateLoader<'a> {
) -> CrateNum { ) -> CrateNum {
let cnum = self.resolve_crate( let cnum = self.resolve_crate(
&None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
).0; ).unwrap_or_else(|err| err.report()).0;
self.update_extern_crate( self.update_extern_crate(
cnum, cnum,
@ -1147,4 +1164,28 @@ impl<'a> CrateLoader<'a> {
cnum cnum
} }
pub fn maybe_process_path_extern(
&mut self,
name: Symbol,
span: Span,
) -> Option<CrateNum> {
let cnum = self.resolve_crate(
&None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
).ok()?.0;
self.update_extern_crate(
cnum,
ExternCrate {
src: ExternCrateSource::Path,
span,
// to have the least priority in `update_extern_crate`
path_len: usize::max_value(),
direct: true,
},
&mut FxHashSet(),
);
Some(cnum)
}
} }

View File

@ -1674,13 +1674,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let mut extern_prelude: FxHashSet<Name> = let mut extern_prelude: FxHashSet<Name> =
session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
if !attr::contains_name(&krate.attrs, "no_core") {
if !attr::contains_name(&krate.attrs, "no_std") { // HACK(eddyb) this ignore the `no_{core,std}` attributes.
extern_prelude.insert(Symbol::intern("std")); // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
} else { // if !attr::contains_name(&krate.attrs, "no_core") {
extern_prelude.insert(Symbol::intern("core")); // if !attr::contains_name(&krate.attrs, "no_std") {
} extern_prelude.insert(Symbol::intern("core"));
} extern_prelude.insert(Symbol::intern("std"));
extern_prelude.insert(Symbol::intern("meta"));
let mut invocations = FxHashMap(); let mut invocations = FxHashMap();
invocations.insert(Mark::root(), invocations.insert(Mark::root(),
@ -1982,7 +1983,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
"access to extern crates through prelude is experimental").emit(); "access to extern crates through prelude is experimental").emit();
} }
let crate_root = self.load_extern_prelude_crate_if_needed(ident); 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, let binding = (crate_root, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas); ident.span, Mark::root()).to_name_binding(self.arenas);
@ -2010,13 +2013,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
None None
} }
fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> {
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);
crate_root
}
fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
-> Option<Module<'a>> { -> Option<Module<'a>> {
if !module.expansion.is_descendant_of(span.ctxt().outer()) { if !module.expansion.is_descendant_of(span.ctxt().outer()) {
@ -4427,15 +4423,24 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if self.session.features_untracked().extern_prelude { if self.session.features_untracked().extern_prelude {
let extern_prelude_names = self.extern_prelude.clone(); let extern_prelude_names = self.extern_prelude.clone();
for &krate_name in extern_prelude_names.iter() { for &name in extern_prelude_names.iter() {
let krate_ident = Ident::with_empty_ctxt(krate_name); let ident = Ident::with_empty_ctxt(name);
let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident); match self.crate_loader.maybe_process_path_extern(name, ident.span) {
Some(crate_id) => {
let crate_root = self.get_module(DefId {
krate: crate_id,
index: CRATE_DEF_INDEX,
});
self.populate_module_if_necessary(&crate_root);
suggestions.extend( suggestions.extend(
self.lookup_import_candidates_from_module( self.lookup_import_candidates_from_module(
lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn lookup_name, namespace, crate_root, ident, &filter_fn
) )
); );
}
None => {}
}
} }
} }

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.
// edition:2018
// Tests that `meta` is whitelisted, even if the crate doesn't exist
// yet (i.e. it causes a different error than `not-whitelisted.rs`).
use meta; //~ ERROR can't find crate for `meta`
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0463]: can't find crate for `meta`
--> $DIR/meta.rs:15:5
|
LL | use meta; //~ ERROR can't find crate for `meta`
| ^^^^ can't find crate
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.

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.
// edition:2018
// Tests that arbitrary crates (other than `core`, `std` and `meta`)
// aren't allowed without `--extern`, even if they're in the sysroot.
use alloc; //~ ERROR unresolved import `alloc`
use test; //~ ERROR unresolved import `test`
use proc_macro; //~ ERROR unresolved import `proc_macro`
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0432]: unresolved import `alloc`
--> $DIR/not-whitelisted.rs:15:5
|
LL | use alloc; //~ ERROR unresolved import `alloc`
| ^^^^^ no `alloc` external crate
error[E0432]: unresolved import `test`
--> $DIR/not-whitelisted.rs:16:5
|
LL | use test; //~ ERROR unresolved import `test`
| ^^^^ no `test` external crate
error[E0432]: unresolved import `proc_macro`
--> $DIR/not-whitelisted.rs:17:5
|
LL | use proc_macro; //~ ERROR unresolved import `proc_macro`
| ^^^^^^^^^^ no `proc_macro` external crate
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0432`.

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.
// run-pass
// edition:2018
// Tests that `core` and `std` are always available.
use core::iter;
use std::io;
// FIXME(eddyb) Add a `meta` crate to the distribution.
// use meta;
fn main() {
for _ in iter::once(()) {
io::stdout();
}
}

View File

@ -12,7 +12,7 @@
// edition:2018 // edition:2018
// compile-pass // compile-pass
// aux-build:remove-extern-crate.rs // aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate --extern core // compile-flags:--extern remove_extern_crate
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]

View File

@ -12,7 +12,7 @@
// edition:2018 // edition:2018
// compile-pass // compile-pass
// aux-build:remove-extern-crate.rs // aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate --extern core // compile-flags:--extern remove_extern_crate
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]