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_trait_imports: FxHashSet<DefId>,
|
||||||
maybe_unused_extern_crates: Vec<(DefId, Span)>,
|
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.
|
// Internal cache for metadata decoding. No need to track deps on this.
|
||||||
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
|
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.
|
// printing the `CrateRoot` so we don't prepend a `crate::` to paths.
|
||||||
let mut is_prelude_crate = false;
|
let mut is_prelude_crate = false;
|
||||||
if let DefPathData::CrateRoot = self.def_key(parent_did).disambiguated_data.data {
|
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;
|
is_prelude_crate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ use ty::subst::{Subst, Substs};
|
|||||||
use ty::util::{IntTypeExt, Discr};
|
use ty::util::{IntTypeExt, Discr};
|
||||||
use ty::walk::TypeWalker;
|
use ty::walk::TypeWalker;
|
||||||
use util::captures::Captures;
|
use util::captures::Captures;
|
||||||
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
|
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||||
use arena::SyncDroplessArena;
|
use arena::SyncDroplessArena;
|
||||||
use session::DataTypeKind;
|
use session::DataTypeKind;
|
||||||
|
|
||||||
@ -141,7 +141,9 @@ pub struct Resolutions {
|
|||||||
pub maybe_unused_trait_imports: NodeSet,
|
pub maybe_unused_trait_imports: NodeSet,
|
||||||
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
|
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
|
||||||
pub export_map: ExportMap,
|
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
@ -790,7 +790,9 @@ where
|
|||||||
trait_map: resolver.trait_map,
|
trait_map: resolver.trait_map,
|
||||||
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
|
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
|
||||||
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
|
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 {
|
analysis: ty::CrateAnalysis {
|
||||||
|
@ -17,7 +17,7 @@ use macros::{InvocationData, ParentScope, LegacyScope};
|
|||||||
use resolve_imports::ImportDirective;
|
use resolve_imports::ImportDirective;
|
||||||
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
||||||
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
|
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 Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||||
use {resolve_error, resolve_struct_error, ResolutionError};
|
use {resolve_error, resolve_struct_error, ResolutionError};
|
||||||
|
|
||||||
@ -28,6 +28,7 @@ use rustc::middle::cstore::CrateStore;
|
|||||||
use rustc_metadata::cstore::LoadedMacro;
|
use rustc_metadata::cstore::LoadedMacro;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::ptr;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
|
||||||
use syntax::ast::{Name, Ident};
|
use syntax::ast::{Name, Ident};
|
||||||
@ -437,13 +438,32 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
let module =
|
let module =
|
||||||
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
||||||
self.populate_module_if_necessary(module);
|
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);
|
self.injected_crate = Some(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
let used = self.process_legacy_macro_imports(item, module, expansion);
|
let used = self.process_legacy_macro_imports(item, module, expansion);
|
||||||
let binding =
|
let binding =
|
||||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
|
(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 {
|
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||||
root_id: item.id,
|
root_id: item.id,
|
||||||
id: item.id,
|
id: item.id,
|
||||||
@ -468,7 +488,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
|
|
||||||
ItemKind::GlobalAsm(..) => {}
|
ItemKind::GlobalAsm(..) => {}
|
||||||
|
|
||||||
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
|
ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
|
||||||
|
|
||||||
ItemKind::Mod(..) => {
|
ItemKind::Mod(..) => {
|
||||||
let def_id = self.definitions.local_def_id(item.id);
|
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)
|
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
|
||||||
// each time.
|
// each time.
|
||||||
let external_crate_names: BTreeSet<Symbol> = self.resolver.extern_prelude
|
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.
|
// Insert a new path segment that we can replace.
|
||||||
let new_path_segment = path[0].clone();
|
let new_path_segment = path[0].clone();
|
||||||
@ -146,10 +146,6 @@ 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
|
// 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`.
|
// that we'll always get `std` before `core`.
|
||||||
for name in external_crate_names.iter().rev() {
|
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
|
// Replace the first after root (a placeholder we inserted) with a crate name
|
||||||
// and check if that is valid.
|
// and check if that is valid.
|
||||||
path[1].name = *name;
|
path[1].name = *name;
|
||||||
@ -160,7 +156,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
return Some(path)
|
return Some(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Remove our placeholder segment.
|
// Remove our placeholder segment.
|
||||||
path.remove(1);
|
path.remove(1);
|
||||||
|
@ -58,6 +58,7 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
|
|||||||
use syntax::ext::base::SyntaxExtension;
|
use syntax::ext::base::SyntaxExtension;
|
||||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||||
use syntax::ext::base::MacroKind;
|
use syntax::ext::base::MacroKind;
|
||||||
|
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
use syntax::util::lev_distance::find_best_match_for_name;
|
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.
|
/// The main resolver class.
|
||||||
///
|
///
|
||||||
/// This is the visitor that walks the whole crate.
|
/// This is the visitor that walks the whole crate.
|
||||||
@ -1352,7 +1359,7 @@ pub struct Resolver<'a, 'b: 'a> {
|
|||||||
graph_root: Module<'a>,
|
graph_root: Module<'a>,
|
||||||
|
|
||||||
prelude: Option<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.
|
/// n.b. This is used only for better diagnostics, not name resolution itself.
|
||||||
has_self: FxHashSet<DefId>,
|
has_self: FxHashSet<DefId>,
|
||||||
@ -1668,15 +1675,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
DefCollector::new(&mut definitions, Mark::root())
|
DefCollector::new(&mut definitions, Mark::root())
|
||||||
.collect_root(crate_name, session.local_crate_disambiguator());
|
.collect_root(crate_name, session.local_crate_disambiguator());
|
||||||
|
|
||||||
let mut extern_prelude: FxHashSet<Name> =
|
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry> =
|
||||||
session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
|
session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
if !attr::contains_name(&krate.attrs, "no_core") {
|
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") {
|
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() {
|
if session.rust_2018() {
|
||||||
extern_prelude.insert(Symbol::intern("meta"));
|
extern_prelude.insert(Ident::from_str("meta"), Default::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1963,22 +1971,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !module.no_implicit_prelude {
|
if !module.no_implicit_prelude {
|
||||||
if ns == TypeNS && self.extern_prelude.contains(&ident.name) {
|
if ns == TypeNS {
|
||||||
let crate_id = if record_used {
|
if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) {
|
||||||
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));
|
return Some(LexicalScopeBinding::Item(binding));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ns == TypeNS && is_known_tool(ident.name) {
|
if ns == TypeNS && is_known_tool(ident.name) {
|
||||||
let binding = (Def::ToolMod, ty::Visibility::Public,
|
let binding = (Def::ToolMod, ty::Visibility::Public,
|
||||||
ident.span, Mark::root()).to_name_binding(self.arenas);
|
ident.span, Mark::root()).to_name_binding(self.arenas);
|
||||||
@ -4018,7 +4015,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
} else {
|
} else {
|
||||||
// Items from the prelude
|
// Items from the prelude
|
||||||
if !module.no_implicit_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 {
|
if let Some(prelude) = self.prelude {
|
||||||
add_module_candidates(prelude, &mut names);
|
add_module_candidates(prelude, &mut names);
|
||||||
}
|
}
|
||||||
@ -4459,11 +4456,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
|
|
||||||
if self.session.rust_2018() {
|
if self.session.rust_2018() {
|
||||||
let extern_prelude_names = self.extern_prelude.clone();
|
let extern_prelude_names = self.extern_prelude.clone();
|
||||||
for &name in extern_prelude_names.iter() {
|
for (ident, _) in extern_prelude_names.into_iter() {
|
||||||
let ident = Ident::with_empty_ctxt(name);
|
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
|
||||||
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name,
|
ident.span) {
|
||||||
ident.span)
|
|
||||||
{
|
|
||||||
let crate_root = self.get_module(DefId {
|
let crate_root = self.get_module(DefId {
|
||||||
krate: crate_id,
|
krate: crate_id,
|
||||||
index: CRATE_DEF_INDEX,
|
index: CRATE_DEF_INDEX,
|
||||||
@ -4825,6 +4820,35 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
self.name_already_seen.insert(name, span);
|
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 {
|
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
|
||||||
|
@ -691,20 +691,15 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
WhereToResolve::ExternPrelude => {
|
WhereToResolve::ExternPrelude => {
|
||||||
if use_prelude && self.extern_prelude.contains(&ident.name) {
|
let mut result = Err(Determinacy::Determined);
|
||||||
let crate_id =
|
if use_prelude {
|
||||||
self.crate_loader.process_path_extern(ident.name, ident.span);
|
if let Some(binding) = self.extern_prelude_get(ident, !record_used,
|
||||||
let crate_root =
|
innermost_result.is_some()) {
|
||||||
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
result = Ok((binding, Flags::PRELUDE, Flags::empty()));
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
WhereToResolve::ToolPrelude => {
|
WhereToResolve::ToolPrelude => {
|
||||||
if use_prelude && is_known_tool(ident.name) {
|
if use_prelude && is_known_tool(ident.name) {
|
||||||
let binding = (Def::ToolMod, ty::Visibility::Public,
|
let binding = (Def::ToolMod, ty::Visibility::Public,
|
||||||
|
@ -21,7 +21,7 @@ use rustc_data_structures::ptr_key::PtrKey;
|
|||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::lint::builtin::BuiltinLintDiagnostics;
|
use rustc::lint::builtin::BuiltinLintDiagnostics;
|
||||||
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
|
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::hir::def::*;
|
||||||
use rustc::session::DiagnosticMessageId;
|
use rustc::session::DiagnosticMessageId;
|
||||||
use rustc::util::nodemap::FxHashSet;
|
use rustc::util::nodemap::FxHashSet;
|
||||||
@ -202,7 +202,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
if !(
|
if !(
|
||||||
ns == TypeNS &&
|
ns == TypeNS &&
|
||||||
!ident.is_path_segment_keyword() &&
|
!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`.
|
// ... unless the crate name is not in the `extern_prelude`.
|
||||||
return binding;
|
return binding;
|
||||||
@ -220,12 +220,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
self.resolve_crate_root(ident)
|
self.resolve_crate_root(ident)
|
||||||
} else if
|
} else if
|
||||||
ns == TypeNS &&
|
ns == TypeNS &&
|
||||||
!ident.is_path_segment_keyword() &&
|
!ident.is_path_segment_keyword()
|
||||||
self.extern_prelude.contains(&ident.name)
|
|
||||||
{
|
{
|
||||||
let crate_id =
|
if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) {
|
||||||
self.crate_loader.process_path_extern(ident.name, ident.span);
|
let module = self.get_module(binding.def().def_id());
|
||||||
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
|
self.populate_module_if_necessary(module);
|
||||||
|
return Ok(binding);
|
||||||
|
} else {
|
||||||
|
return Err(Determined);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Determined);
|
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;
|
let uniform_paths_feature = self.session.features_untracked().uniform_paths;
|
||||||
for ((span, _, ns), results) in uniform_paths_canaries {
|
for ((span, _, ns), results) in uniform_paths_canaries {
|
||||||
let name = results.name;
|
let name = results.name;
|
||||||
let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) {
|
let external_crate = if ns == TypeNS {
|
||||||
let crate_id =
|
self.extern_prelude_get(Ident::with_empty_ctxt(name), true, false)
|
||||||
self.crate_loader.process_path_extern(name, span);
|
.map(|binding| binding.def())
|
||||||
Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX }))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -1021,6 +1023,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||||||
Some(this.dummy_binding);
|
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,
|
// If the extern crate isn't in the extern prelude,
|
||||||
// there is no way it can be written as an `use`.
|
// there is no way it can be written as an `use`.
|
||||||
let orig_name = extern_crate.orig_name.unwrap_or(item.name);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +476,9 @@ pub fn run_core(search_paths: SearchPaths,
|
|||||||
trait_map: resolver.trait_map.clone(),
|
trait_map: resolver.trait_map.clone(),
|
||||||
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
|
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
|
||||||
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.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 {
|
let analysis = ty::CrateAnalysis {
|
||||||
access_levels: Lrc::new(AccessLevels::default()),
|
access_levels: Lrc::new(AccessLevels::default()),
|
||||||
|
@ -501,6 +501,9 @@ declare_features! (
|
|||||||
|
|
||||||
// Allows `const _: TYPE = VALUE`
|
// Allows `const _: TYPE = VALUE`
|
||||||
(active, underscore_const_names, "1.31.0", Some(54912), None),
|
(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! (
|
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
|
--> $DIR/resolve-error.rs:54:10
|
||||||
|
|
|
|
||||||
LL | #[derive(attr_proc_macra)]
|
LL | #[derive(attr_proc_macra)]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
|
||||||
|
|
||||||
error: cannot find macro `FooWithLongNama!` in this scope
|
error: cannot find macro `FooWithLongNama!` in this scope
|
||||||
--> $DIR/resolve-error.rs:59:5
|
--> $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`
|
LL | use m2::*; // glob-import user-defined `std`
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
note: `std` could also refer to the name defined here
|
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
|
= note: consider adding an explicit import of `std` to disambiguate
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user