mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
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:
commit
365b9001e5
@ -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>>>,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
|
@ -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! (
|
||||
|
@ -0,0 +1,9 @@
|
||||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(extern_crate_item_prelude)]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream; // OK
|
||||
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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`.
|
17
src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
Normal file
17
src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
Normal 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() {}
|
22
src/test/ui/imports/extern-prelude-extern-crate-fail.rs
Normal file
22
src/test/ui/imports/extern-prelude-extern-crate-fail.rs
Normal 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() {}
|
18
src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
Normal file
18
src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
Normal 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`.
|
14
src/test/ui/imports/extern-prelude-extern-crate-pass.rs
Normal file
14
src/test/ui/imports/extern-prelude-extern-crate-pass.rs
Normal 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() {}
|
@ -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() {}
|
@ -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`.
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user