Auto merge of #54658 - petrochenkov:experelude, r=nikomatsakis

Add `extern crate` items to extern prelude

With this patch each `extern crate orig_name as name` item adds name `name` into the extern prelude, as if it was passed with `--extern`.

What changes this causes in practice?
Almost none! After all, `--extern` passed from Cargo was supposed to replace `extern crate` items in source, so if some code has `extern crate` item (or had it on 2015 edition), then it most likely uses `--extern` as well...

... with exception of a few important cases.

- Crates using `proc_macro`. `proc_macro` is not passed with `--extern` right now and is therefore not in extern prelude.
Together with 2018 edition import behavior this causes problems like https://github.com/rust-lang/rust/issues/54418, e.g.
    ```rust
    extern crate proc_macro;
    use proc_macro::TokenStream;
    ```
    doesn't work.
It starts working after this patch.

- `#[no_std]` crates using `std` conditionally, like @aturon described in https://github.com/rust-lang/rust/issues/53166#issuecomment-425219286, and still wanting to write `std` instead of `crate::std`. This PR covers that case as well.
This allows us to revert placing `std` into the extern prelude unconditionally, which was, I think, a [bad idea](https://github.com/rust-lang/rust/issues/53166#issuecomment-425117829).

- Later `extern crate` syntax can be extended to support adding an alias to some local path to extern prelude, as it may be required for resolving https://github.com/rust-lang/rust/issues/54647.

Notes:
- Only `extern crate` items from the root module added to the prelude, mostly because this behavior for items from inner modules would look very strange, rather than for technical reasons.
This means you can opt out from the prelude additions with something like
    ```rust
    mod inner {
        pub(crate) extern crate foo;
    }
    use inner::foo;
    ```
- I haven't updated logic for 2018 import canaries to work fully correctly with this. The cases where it matters are pretty exotic (the `extern crate` item must be "sufficiently macro expanded") and I'd rather spend the time on eliminating the canaries entirely.
This commit is contained in:
bors 2018-10-25 09:18:17 +00:00
commit 365b9001e5
23 changed files with 369 additions and 79 deletions

View File

@ -931,7 +931,9 @@ pub struct GlobalCtxt<'tcx> {
maybe_unused_trait_imports: FxHashSet<DefId>,
maybe_unused_extern_crates: Vec<(DefId, Span)>,
pub extern_prelude: FxHashSet<ast::Name>,
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<ast::Name, bool>,
// Internal cache for metadata decoding. No need to track deps on this.
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,

View File

@ -343,7 +343,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// printing the `CrateRoot` so we don't prepend a `crate::` to paths.
let mut is_prelude_crate = false;
if let DefPathData::CrateRoot = self.def_key(parent_did).disambiguated_data.data {
if self.extern_prelude.contains(&data.as_interned_str().as_symbol()) {
if self.extern_prelude.contains_key(&data.as_interned_str().as_symbol()) {
is_prelude_crate = true;
}
}

View File

@ -36,7 +36,7 @@ use ty::subst::{Subst, Substs};
use ty::util::{IntTypeExt, Discr};
use ty::walk::TypeWalker;
use util::captures::Captures;
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
use arena::SyncDroplessArena;
use session::DataTypeKind;
@ -141,7 +141,9 @@ pub struct Resolutions {
pub maybe_unused_trait_imports: NodeSet,
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
pub export_map: ExportMap,
pub extern_prelude: FxHashSet<Name>,
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<Name, bool>,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]

View File

@ -790,7 +790,9 @@ where
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
extern_prelude: resolver.extern_prelude,
extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
(ident.name, entry.introduced_by_item)
}).collect(),
},
analysis: ty::CrateAnalysis {

View File

@ -17,7 +17,7 @@ use macros::{InvocationData, ParentScope, LegacyScope};
use resolve_imports::ImportDirective;
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas};
use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
use Namespace::{self, TypeNS, ValueNS, MacroNS};
use {resolve_error, resolve_struct_error, ResolutionError};
@ -28,6 +28,7 @@ use rustc::middle::cstore::CrateStore;
use rustc_metadata::cstore::LoadedMacro;
use std::cell::Cell;
use std::ptr;
use rustc_data_structures::sync::Lrc;
use syntax::ast::{Name, Ident};
@ -437,13 +438,32 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let module =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(module);
if injected_crate_name().map_or(false, |name| item.ident.name == name) {
if injected_crate_name().map_or(false, |name| ident.name == name) {
self.injected_crate = Some(module);
}
let used = self.process_legacy_macro_imports(item, module, expansion);
let binding =
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
if ptr::eq(self.current_module, self.graph_root) {
if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
if expansion != Mark::root() && orig_name.is_some() &&
entry.extern_crate_item.is_none() {
self.session.span_err(item.span, "macro-expanded `extern crate` items \
cannot shadow names passed with \
`--extern`");
}
}
let entry = self.extern_prelude.entry(ident.modern())
.or_insert(ExternPreludeEntry {
extern_crate_item: None,
introduced_by_item: true,
});
entry.extern_crate_item = Some(binding);
if orig_name.is_some() {
entry.introduced_by_item = true;
}
}
let directive = self.arenas.alloc_import_directive(ImportDirective {
root_id: item.id,
id: item.id,
@ -468,7 +488,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
ItemKind::GlobalAsm(..) => {}
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
ItemKind::Mod(..) => {
let def_id = self.definitions.local_def_id(item.id);

View File

@ -137,7 +137,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
// each time.
let external_crate_names: BTreeSet<Symbol> = self.resolver.extern_prelude
.clone().drain().collect();
.iter().map(|(ident, _)| ident.name).collect();
// Insert a new path segment that we can replace.
let new_path_segment = path[0].clone();
@ -146,19 +146,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// Iterate in reverse so that we start with crates at the end of the alphabet. This means
// that we'll always get `std` before `core`.
for name in external_crate_names.iter().rev() {
let ident = Ident::with_empty_ctxt(*name);
// Calling `maybe_process_path_extern` ensures that we're only running `resolve_path`
// on a crate name that won't ICE.
if let Some(_) = self.crate_loader.maybe_process_path_extern(*name, ident.span) {
// Replace the first after root (a placeholder we inserted) with a crate name
// and check if that is valid.
path[1].name = *name;
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {
return Some(path)
}
// Replace the first after root (a placeholder we inserted) with a crate name
// and check if that is valid.
path[1].name = *name;
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {
return Some(path)
}
}

View File

@ -58,6 +58,7 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::base::MacroKind;
use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::symbol::{Symbol, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
@ -1340,6 +1341,12 @@ impl PrimitiveTypeTable {
}
}
#[derive(Default, Clone)]
pub struct ExternPreludeEntry<'a> {
extern_crate_item: Option<&'a NameBinding<'a>>,
pub introduced_by_item: bool,
}
/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
@ -1352,7 +1359,7 @@ pub struct Resolver<'a, 'b: 'a> {
graph_root: Module<'a>,
prelude: Option<Module<'a>>,
pub extern_prelude: FxHashSet<Name>,
pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
@ -1668,15 +1675,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, session.local_crate_disambiguator());
let mut extern_prelude: FxHashSet<Name> =
session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry> =
session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
.collect();
if !attr::contains_name(&krate.attrs, "no_core") {
extern_prelude.insert(Symbol::intern("core"));
extern_prelude.insert(Ident::from_str("core"), Default::default());
if !attr::contains_name(&krate.attrs, "no_std") {
extern_prelude.insert(Symbol::intern("std"));
extern_prelude.insert(Ident::from_str("std"), Default::default());
if session.rust_2018() {
extern_prelude.insert(Symbol::intern("meta"));
extern_prelude.insert(Ident::from_str("meta"), Default::default());
}
}
}
@ -1963,21 +1971,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
if !module.no_implicit_prelude {
if ns == TypeNS && self.extern_prelude.contains(&ident.name) {
let crate_id = if record_used {
self.crate_loader.process_path_extern(ident.name, ident.span)
} else if let Some(crate_id) =
self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
crate_id
} else {
return None;
};
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 ns == TypeNS {
if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) {
return Some(LexicalScopeBinding::Item(binding));
}
}
if ns == TypeNS && is_known_tool(ident.name) {
let binding = (Def::ToolMod, ty::Visibility::Public,
@ -4018,7 +4015,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} else {
// Items from the prelude
if !module.no_implicit_prelude {
names.extend(self.extern_prelude.iter().cloned());
names.extend(self.extern_prelude.iter().map(|(ident, _)| ident.name));
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
@ -4459,11 +4456,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if self.session.rust_2018() {
let extern_prelude_names = self.extern_prelude.clone();
for &name in extern_prelude_names.iter() {
let ident = Ident::with_empty_ctxt(name);
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name,
ident.span)
{
for (ident, _) in extern_prelude_names.into_iter() {
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
ident.span) {
let crate_root = self.get_module(DefId {
krate: crate_id,
index: CRATE_DEF_INDEX,
@ -4825,6 +4820,35 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
err.emit();
self.name_already_seen.insert(name, span);
}
fn extern_prelude_get(&mut self, ident: Ident, speculative: bool, skip_feature_gate: bool)
-> Option<&'a NameBinding<'a>> {
self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
if let Some(binding) = entry.extern_crate_item {
if !speculative && !skip_feature_gate && entry.introduced_by_item &&
!self.session.features_untracked().extern_crate_item_prelude {
emit_feature_err(&self.session.parse_sess, "extern_crate_item_prelude",
ident.span, GateIssue::Language,
"use of extern prelude names introduced \
with `extern crate` items is unstable");
}
Some(binding)
} else {
let crate_id = if !speculative {
self.crate_loader.process_path_extern(ident.name, ident.span)
} else if let Some(crate_id) =
self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
crate_id
} else {
return None;
};
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(&crate_root);
Some((crate_root, ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas))
}
})
}
}
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {

View File

@ -691,19 +691,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
}
WhereToResolve::ExternPrelude => {
if use_prelude && self.extern_prelude.contains(&ident.name) {
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);
Ok((binding, Flags::PRELUDE, Flags::empty()))
} else {
Err(Determinacy::Determined)
let mut result = Err(Determinacy::Determined);
if use_prelude {
if let Some(binding) = self.extern_prelude_get(ident, !record_used,
innermost_result.is_some()) {
result = Ok((binding, Flags::PRELUDE, Flags::empty()));
}
}
result
}
WhereToResolve::ToolPrelude => {
if use_prelude && is_known_tool(ident.name) {

View File

@ -21,7 +21,7 @@ use rustc_data_structures::ptr_key::PtrKey;
use rustc::ty;
use rustc::lint::builtin::BuiltinLintDiagnostics;
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::def_id::DefId;
use rustc::hir::def::*;
use rustc::session::DiagnosticMessageId;
use rustc::util::nodemap::FxHashSet;
@ -202,7 +202,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
if !(
ns == TypeNS &&
!ident.is_path_segment_keyword() &&
self.extern_prelude.contains(&ident.name)
self.extern_prelude.contains_key(&ident.modern())
) {
// ... unless the crate name is not in the `extern_prelude`.
return binding;
@ -220,12 +220,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
self.resolve_crate_root(ident)
} else if
ns == TypeNS &&
!ident.is_path_segment_keyword() &&
self.extern_prelude.contains(&ident.name)
!ident.is_path_segment_keyword()
{
let crate_id =
self.crate_loader.process_path_extern(ident.name, ident.span);
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) {
let module = self.get_module(binding.def().def_id());
self.populate_module_if_necessary(module);
return Ok(binding);
} else {
return Err(Determined);
}
} else {
return Err(Determined);
};
@ -738,10 +741,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let uniform_paths_feature = self.session.features_untracked().uniform_paths;
for ((span, _, ns), results) in uniform_paths_canaries {
let name = results.name;
let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) {
let crate_id =
self.crate_loader.process_path_extern(name, span);
Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX }))
let external_crate = if ns == TypeNS {
self.extern_prelude_get(Ident::with_empty_ctxt(name), true, false)
.map(|binding| binding.def())
} else {
None
};
@ -1021,6 +1023,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
Some(this.dummy_binding);
}
}
if record_used && ns == TypeNS {
if let ModuleOrUniformRoot::UniformRoot(..) = module {
// Make sure single-segment import is resolved non-speculatively
// at least once to report the feature error.
this.extern_prelude_get(ident, false, false);
}
}
}
});

View File

@ -164,7 +164,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
// If the extern crate isn't in the extern prelude,
// there is no way it can be written as an `use`.
let orig_name = extern_crate.orig_name.unwrap_or(item.name);
if !tcx.extern_prelude.contains(&orig_name) {
if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
continue;
}

View File

@ -476,7 +476,9 @@ pub fn run_core(search_paths: SearchPaths,
trait_map: resolver.trait_map.clone(),
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
extern_prelude: resolver.extern_prelude.clone(),
extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
(ident.name, entry.introduced_by_item)
}).collect(),
};
let analysis = ty::CrateAnalysis {
access_levels: Lrc::new(AccessLevels::default()),

View File

@ -501,6 +501,9 @@ declare_features! (
// Allows `const _: TYPE = VALUE`
(active, underscore_const_names, "1.31.0", Some(54912), None),
// `extern crate foo as bar;` puts `bar` into extern prelude.
(active, extern_crate_item_prelude, "1.31.0", Some(54658), None),
);
declare_features! (

View File

@ -0,0 +1,9 @@
// compile-pass
// edition:2018
#![feature(extern_crate_item_prelude)]
extern crate proc_macro;
use proc_macro::TokenStream; // OK
fn main() {}

View File

@ -20,7 +20,7 @@ error: cannot find derive macro `attr_proc_macra` in this scope
--> $DIR/resolve-error.rs:54:10
|
LL | #[derive(attr_proc_macra)]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
error: cannot find macro `FooWithLongNama!` in this scope
--> $DIR/resolve-error.rs:59:5

View File

@ -0,0 +1,46 @@
// edition:2018
#![feature(alloc)]
extern crate alloc;
mod in_scope {
fn check() {
let v = alloc::vec![0];
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
type A = alloc::boxed::Box<u8>;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
}
}
mod absolute {
fn check() {
let v = ::alloc::vec![0];
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
type A = ::alloc::boxed::Box<u8>;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
}
}
mod import_in_scope {
use alloc;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
use alloc::boxed;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
}
mod import_absolute {
use ::alloc;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
use ::alloc::boxed;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
}
extern crate alloc as core;
mod unrelated_crate_renamed {
type A = core::boxed::Box<u8>;
//~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
}
fn main() {}

View File

@ -0,0 +1,75 @@
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:26:9
|
LL | use alloc;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:28:9
|
LL | use alloc::boxed;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:33:11
|
LL | use ::alloc;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:35:11
|
LL | use ::alloc::boxed;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:9:17
|
LL | let v = alloc::vec![0];
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:11:18
|
LL | type A = alloc::boxed::Box<u8>;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:18:19
|
LL | let v = ::alloc::vec![0];
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:20:20
|
LL | type A = ::alloc::boxed::Box<u8>;
| ^^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
--> $DIR/feature-gate-extern_crate_item_prelude.rs:42:14
|
LL | type A = core::boxed::Box<u8>;
| ^^^^
|
= help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,17 @@
// compile-pass
// compile-flags:--cfg my_feature
#![feature(extern_crate_item_prelude)]
#![no_std]
#[cfg(my_feature)]
extern crate std;
mod m {
#[cfg(my_feature)]
fn conditional() {
std::vec::Vec::<u8>::new(); // OK
}
}
fn main() {}

View File

@ -0,0 +1,22 @@
// aux-build:two_macros.rs
// compile-flags:--extern non_existent
mod n {
extern crate two_macros;
}
mod m {
fn check() {
two_macros::m!(); //~ ERROR failed to resolve. Use of undeclared type or module `two_macros`
}
}
macro_rules! define_std_as_non_existent {
() => {
extern crate std as non_existent;
//~^ ERROR `extern crate` items cannot shadow names passed with `--extern`
}
}
define_std_as_non_existent!();
fn main() {}

View File

@ -0,0 +1,18 @@
error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
--> $DIR/extern-prelude-extern-crate-fail.rs:16:9
|
LL | extern crate std as non_existent;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | define_std_as_non_existent!();
| ------------------------------ in this macro invocation
error[E0433]: failed to resolve. Use of undeclared type or module `two_macros`
--> $DIR/extern-prelude-extern-crate-fail.rs:10:9
|
LL | two_macros::m!(); //~ ERROR failed to resolve. Use of undeclared type or module `two_macros`
| ^^^^^^^^^^ Use of undeclared type or module `two_macros`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0433`.

View File

@ -0,0 +1,14 @@
// compile-pass
// aux-build:two_macros.rs
#![feature(extern_crate_item_prelude)]
extern crate two_macros;
mod m {
fn check() {
two_macros::m!(); // OK
}
}
fn main() {}

View File

@ -0,0 +1,19 @@
// aux-build:two_macros.rs
#![feature(extern_crate_item_prelude)]
macro_rules! define_vec {
() => {
extern crate std as Vec;
}
}
define_vec!();
mod m {
fn check() {
Vec::panic!(); //~ ERROR `Vec` is ambiguous
}
}
fn main() {}

View File

@ -0,0 +1,20 @@
error[E0659]: `Vec` is ambiguous
--> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:15:9
|
LL | Vec::panic!(); //~ ERROR `Vec` is ambiguous
| ^^^ ambiguous name
|
note: `Vec` could refer to the name defined here
--> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:7:9
|
LL | extern crate std as Vec;
| ^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | define_vec!();
| -------------- in this macro invocation
note: `Vec` could also refer to the name defined here
= note: macro-expanded items do not shadow when used in a macro invocation path
error: aborting due to previous error
For more information about this error, try `rustc --explain E0659`.

View File

@ -10,10 +10,6 @@ note: `std` could refer to the name imported here
LL | use m2::*; // glob-import user-defined `std`
| ^^^^^
note: `std` could also refer to the name defined here
--> $DIR/macro-path-prelude-shadowing.rs:39:9
|
LL | std::panic!(); //~ ERROR `std` is ambiguous
| ^^^
= note: consider adding an explicit import of `std` to disambiguate
error: aborting due to previous error