diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index e28bb26082040..6eef2397f9c6e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -100,6 +100,18 @@ enum LoadResult { 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> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { @@ -268,16 +280,17 @@ impl<'a> CrateLoader<'a> { (cnum, cmeta) } - fn resolve_crate(&mut self, - root: &Option, - ident: Symbol, - name: Symbol, - hash: Option<&Svh>, - extra_filename: Option<&str>, - span: Span, - path_kind: PathKind, - mut dep_kind: DepKind) - -> (CrateNum, Lrc) { + fn resolve_crate<'b>( + &'b mut self, + root: &'b Option, + ident: Symbol, + name: Symbol, + hash: Option<&'b Svh>, + extra_filename: Option<&'b str>, + span: Span, + path_kind: PathKind, + mut dep_kind: DepKind, + ) -> Result<(CrateNum, Lrc), LoadError<'b>> { info!("resolving crate `extern crate {} as {}`", name, ident); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { LoadResult::Previous(cnum) @@ -321,7 +334,7 @@ impl<'a> CrateLoader<'a> { }; self.load(&mut proc_macro_locator) - }).unwrap_or_else(|| locate_ctxt.report_errs()) + }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))? }; match result { @@ -333,10 +346,10 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - (cnum, data) + Ok((cnum, data)) } 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( root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, PathKind::Dependency, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); local_cnum })).collect() } @@ -695,7 +708,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; 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 // 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 (_, data) = 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 if !data.root.sanitizer_runtime { @@ -826,7 +841,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (_, data) = 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 if !data.root.profiler_runtime { @@ -946,7 +962,8 @@ impl<'a> CrateLoader<'a> { None, DUMMY_SP, PathKind::Crate, - DepKind::Implicit); + DepKind::Implicit) + .unwrap_or_else(|err| err.report()); self.sess.injected_allocator.set(Some(cnum)); data }) @@ -1103,7 +1120,7 @@ impl<'a> CrateLoader<'a> { let (cnum, ..) = self.resolve_crate( &None, item.ident.name, orig_name, None, None, item.span, PathKind::Crate, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -1131,7 +1148,7 @@ impl<'a> CrateLoader<'a> { ) -> CrateNum { let cnum = self.resolve_crate( &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit - ).0; + ).unwrap_or_else(|err| err.report()).0; self.update_extern_crate( cnum, @@ -1147,4 +1164,28 @@ impl<'a> CrateLoader<'a> { cnum } + + pub fn maybe_process_path_extern( + &mut self, + name: Symbol, + span: Span, + ) -> Option { + 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) + } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f0ff8c419fd46..10dddfed6a577 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1674,13 +1674,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut extern_prelude: FxHashSet = 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") { - extern_prelude.insert(Symbol::intern("std")); - } else { - extern_prelude.insert(Symbol::intern("core")); - } - } + + // HACK(eddyb) this ignore the `no_{core,std}` attributes. + // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`. + // if !attr::contains_name(&krate.attrs, "no_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(); invocations.insert(Mark::root(), @@ -1982,7 +1983,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { "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, ident.span, Mark::root()).to_name_binding(self.arenas); @@ -2010,13 +2013,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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) -> Option> { 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 { let extern_prelude_names = self.extern_prelude.clone(); - for &krate_name in extern_prelude_names.iter() { - let krate_ident = Ident::with_empty_ctxt(krate_name); - let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident); + for &name in extern_prelude_names.iter() { + let ident = Ident::with_empty_ctxt(name); + 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( - self.lookup_import_candidates_from_module( - lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn - ) - ); + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn + ) + ); + } + None => {} + } } } diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs new file mode 100644 index 0000000000000..499a322593c60 --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr new file mode 100644 index 0000000000000..b8a9b54d26bca --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr @@ -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`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs new file mode 100644 index 0000000000000..f95961d2a9b56 --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr new file mode 100644 index 0000000000000..0865bd6bea52a --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr @@ -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`. diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs new file mode 100644 index 0000000000000..dfd9fbd27746b --- /dev/null +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs @@ -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 or the MIT license +// , 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(); + } +} diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed index 895da74afd767..cdae815b200d5 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.fixed +++ b/src/test/ui/rust-2018/remove-extern-crate.fixed @@ -12,7 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs -// compile-flags:--extern remove_extern_crate --extern core +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs index c03431a6b8852..4984da802c05b 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.rs +++ b/src/test/ui/rust-2018/remove-extern-crate.rs @@ -12,7 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs -// compile-flags:--extern remove_extern_crate --extern core +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)]