Add extern crate
items to extern prelude
This commit is contained in:
parent
f99911a4a0
commit
0f625ac48d
@ -931,7 +931,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||
|
||||
maybe_unused_trait_imports: FxHashSet<DefId>,
|
||||
maybe_unused_extern_crates: Vec<(DefId, Span)>,
|
||||
pub extern_prelude: FxHashSet<ast::Name>,
|
||||
pub extern_prelude: FxHashMap<ast::Name, bool /* introduced by item */>,
|
||||
|
||||
// Internal cache for metadata decoding. No need to track deps on this.
|
||||
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
|
||||
|
@ -343,7 +343,7 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId, pushed_prelude_cra
|
||||
// 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::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,7 @@ 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>,
|
||||
pub extern_prelude: FxHashMap<Name, bool /* introduced by item */>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
|
@ -790,7 +790,9 @@ pub fn phase_2_configure_and_expand<F>(
|
||||
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 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_metadata::cstore::LoadedMacro;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
use syntax::ast::{Name, Ident};
|
||||
@ -437,13 +438,19 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
||||
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) {
|
||||
self.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry {
|
||||
extern_crate_item: None,
|
||||
introduced_by_item: true,
|
||||
}).extern_crate_item = Some(binding);
|
||||
}
|
||||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
@ -468,7 +475,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
||||
|
||||
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 @@ fn make_external_crate_suggestion(
|
||||
// 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 @@ fn make_external_crate_suggestion(
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1340,6 +1340,12 @@ fn intern(&mut self, string: &str, primitive_type: PrimTy) {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 +1358,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 +1674,16 @@ pub fn new(session: &'a Session,
|
||||
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 +1970,10 @@ fn resolve_ident_in_lexical_scope(&mut self,
|
||||
}
|
||||
|
||||
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) {
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
}
|
||||
}
|
||||
if ns == TypeNS && is_known_tool(ident.name) {
|
||||
let binding = (Def::ToolMod, ty::Visibility::Public,
|
||||
@ -4018,7 +4014,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
|
||||
} 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 +4455,9 @@ fn lookup_import_candidates<FilterFn>(&mut self,
|
||||
|
||||
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 +4819,28 @@ fn report_conflict<'b>(&mut self,
|
||||
err.emit();
|
||||
self.name_already_seen.insert(name, span);
|
||||
}
|
||||
|
||||
fn extern_prelude_get(&mut self, ident: Ident, speculative: bool)
|
||||
-> Option<&'a NameBinding<'a>> {
|
||||
self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
|
||||
if let Some(binding) = entry.extern_crate_item {
|
||||
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,13 @@ struct Flags: u8 {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
result = Ok((binding, Flags::PRELUDE, Flags::empty()));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
WhereToResolve::ToolPrelude => {
|
||||
if use_prelude && is_known_tool(ident.name) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
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 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
|
||||
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 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
|
||||
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) {
|
||||
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 @@ struct UniformPathsCanaryResults<'a> {
|
||||
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)
|
||||
.map(|binding| binding.def())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
// compile-pass
|
||||
// edition:2018
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream; // OK
|
||||
|
||||
fn main() {}
|
16
src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
Normal file
16
src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// compile-pass
|
||||
// compile-flags:--cfg my_feature
|
||||
|
||||
#![no_std]
|
||||
|
||||
#[cfg(my_feature)]
|
||||
extern crate std;
|
||||
|
||||
mod m {
|
||||
#[cfg(my_feature)]
|
||||
fn conditional() {
|
||||
std::vec::Vec::<u8>::new(); // OK
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
13
src/test/ui/imports/extern-prelude-extern-crate-fail.rs
Normal file
13
src/test/ui/imports/extern-prelude-extern-crate-fail.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// aux-build:two_macros.rs
|
||||
|
||||
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`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0433]: failed to resolve. Use of undeclared type or module `two_macros`
|
||||
--> $DIR/extern-prelude-extern-crate-fail.rs:9: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 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
12
src/test/ui/imports/extern-prelude-extern-crate-pass.rs
Normal file
12
src/test/ui/imports/extern-prelude-extern-crate-pass.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// compile-pass
|
||||
// aux-build:two_macros.rs
|
||||
|
||||
extern crate two_macros;
|
||||
|
||||
mod m {
|
||||
fn check() {
|
||||
two_macros::m!(); // OK
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
// aux-build:two_macros.rs
|
||||
|
||||
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:13: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:5: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