Skip to content

Commit 0f625ac

Browse files
committed
Add extern crate items to extern prelude
1 parent f99911a commit 0f625ac

18 files changed

+183
-77
lines changed

src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ pub struct GlobalCtxt<'tcx> {
931931

932932
maybe_unused_trait_imports: FxHashSet<DefId>,
933933
maybe_unused_extern_crates: Vec<(DefId, Span)>,
934-
pub extern_prelude: FxHashSet<ast::Name>,
934+
pub extern_prelude: FxHashMap<ast::Name, bool /* introduced by item */>,
935935

936936
// Internal cache for metadata decoding. No need to track deps on this.
937937
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,

src/librustc/ty/item_path.rs

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

src/librustc/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use ty::subst::{Subst, Substs};
3636
use ty::util::{IntTypeExt, Discr};
3737
use ty::walk::TypeWalker;
3838
use util::captures::Captures;
39-
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
39+
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
4040
use arena::SyncDroplessArena;
4141
use session::DataTypeKind;
4242

@@ -141,7 +141,7 @@ pub struct Resolutions {
141141
pub maybe_unused_trait_imports: NodeSet,
142142
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
143143
pub export_map: ExportMap,
144-
pub extern_prelude: FxHashSet<Name>,
144+
pub extern_prelude: FxHashMap<Name, bool /* introduced by item */>,
145145
}
146146

147147
#[derive(Clone, Copy, PartialEq, Eq, Debug)]

src/librustc_driver/driver.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,9 @@ where
790790
trait_map: resolver.trait_map,
791791
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
792792
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
793-
extern_prelude: resolver.extern_prelude,
793+
extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
794+
(ident.name, entry.introduced_by_item)
795+
}).collect(),
794796
},
795797

796798
analysis: ty::CrateAnalysis {

src/librustc_resolve/build_reduced_graph.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use macros::{InvocationData, ParentScope, LegacyScope};
1717
use resolve_imports::ImportDirective;
1818
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
1919
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
20-
use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas};
20+
use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
2121
use Namespace::{self, TypeNS, ValueNS, MacroNS};
2222
use {resolve_error, resolve_struct_error, ResolutionError};
2323

@@ -28,6 +28,7 @@ use rustc::middle::cstore::CrateStore;
2828
use rustc_metadata::cstore::LoadedMacro;
2929

3030
use std::cell::Cell;
31+
use std::ptr;
3132
use rustc_data_structures::sync::Lrc;
3233

3334
use syntax::ast::{Name, Ident};
@@ -437,13 +438,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
437438
let module =
438439
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
439440
self.populate_module_if_necessary(module);
440-
if injected_crate_name().map_or(false, |name| item.ident.name == name) {
441+
if injected_crate_name().map_or(false, |name| ident.name == name) {
441442
self.injected_crate = Some(module);
442443
}
443444

444445
let used = self.process_legacy_macro_imports(item, module, expansion);
445446
let binding =
446447
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
448+
if ptr::eq(self.current_module, self.graph_root) {
449+
self.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry {
450+
extern_crate_item: None,
451+
introduced_by_item: true,
452+
}).extern_crate_item = Some(binding);
453+
}
447454
let directive = self.arenas.alloc_import_directive(ImportDirective {
448455
root_id: item.id,
449456
id: item.id,
@@ -468,7 +475,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
468475

469476
ItemKind::GlobalAsm(..) => {}
470477

471-
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
478+
ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
472479

473480
ItemKind::Mod(..) => {
474481
let def_id = self.definitions.local_def_id(item.id);

src/librustc_resolve/error_reporting.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
137137
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
138138
// each time.
139139
let external_crate_names: BTreeSet<Symbol> = self.resolver.extern_prelude
140-
.clone().drain().collect();
140+
.iter().map(|(ident, _)| ident.name).collect();
141141

142142
// Insert a new path segment that we can replace.
143143
let new_path_segment = path[0].clone();
@@ -146,19 +146,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
146146
// Iterate in reverse so that we start with crates at the end of the alphabet. This means
147147
// that we'll always get `std` before `core`.
148148
for name in external_crate_names.iter().rev() {
149-
let ident = Ident::with_empty_ctxt(*name);
150-
// Calling `maybe_process_path_extern` ensures that we're only running `resolve_path`
151-
// on a crate name that won't ICE.
152-
if let Some(_) = self.crate_loader.maybe_process_path_extern(*name, ident.span) {
153-
// Replace the first after root (a placeholder we inserted) with a crate name
154-
// and check if that is valid.
155-
path[1].name = *name;
156-
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
157-
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
158-
name, path, result);
159-
if let PathResult::Module(..) = result {
160-
return Some(path)
161-
}
149+
// Replace the first after root (a placeholder we inserted) with a crate name
150+
// and check if that is valid.
151+
path[1].name = *name;
152+
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
153+
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
154+
name, path, result);
155+
if let PathResult::Module(..) = result {
156+
return Some(path)
162157
}
163158
}
164159

src/librustc_resolve/lib.rs

+43-27
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,12 @@ impl PrimitiveTypeTable {
13401340
}
13411341
}
13421342

1343+
#[derive(Default, Clone)]
1344+
pub struct ExternPreludeEntry<'a> {
1345+
extern_crate_item: Option<&'a NameBinding<'a>>,
1346+
pub introduced_by_item: bool,
1347+
}
1348+
13431349
/// The main resolver class.
13441350
///
13451351
/// This is the visitor that walks the whole crate.
@@ -1352,7 +1358,7 @@ pub struct Resolver<'a, 'b: 'a> {
13521358
graph_root: Module<'a>,
13531359

13541360
prelude: Option<Module<'a>>,
1355-
pub extern_prelude: FxHashSet<Name>,
1361+
pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
13561362

13571363
/// n.b. This is used only for better diagnostics, not name resolution itself.
13581364
has_self: FxHashSet<DefId>,
@@ -1668,15 +1674,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
16681674
DefCollector::new(&mut definitions, Mark::root())
16691675
.collect_root(crate_name, session.local_crate_disambiguator());
16701676

1671-
let mut extern_prelude: FxHashSet<Name> =
1672-
session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
1677+
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry> =
1678+
session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
1679+
.collect();
16731680

16741681
if !attr::contains_name(&krate.attrs, "no_core") {
1675-
extern_prelude.insert(Symbol::intern("core"));
1682+
extern_prelude.insert(Ident::from_str("core"), Default::default());
16761683
if !attr::contains_name(&krate.attrs, "no_std") {
1677-
extern_prelude.insert(Symbol::intern("std"));
1684+
extern_prelude.insert(Ident::from_str("std"), Default::default());
16781685
if session.rust_2018() {
1679-
extern_prelude.insert(Symbol::intern("meta"));
1686+
extern_prelude.insert(Ident::from_str("meta"), Default::default());
16801687
}
16811688
}
16821689
}
@@ -1963,21 +1970,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19631970
}
19641971

19651972
if !module.no_implicit_prelude {
1966-
if ns == TypeNS && self.extern_prelude.contains(&ident.name) {
1967-
let crate_id = if record_used {
1968-
self.crate_loader.process_path_extern(ident.name, ident.span)
1969-
} else if let Some(crate_id) =
1970-
self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
1971-
crate_id
1972-
} else {
1973-
return None;
1974-
};
1975-
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
1976-
self.populate_module_if_necessary(&crate_root);
1977-
1978-
let binding = (crate_root, ty::Visibility::Public,
1979-
ident.span, Mark::root()).to_name_binding(self.arenas);
1980-
return Some(LexicalScopeBinding::Item(binding));
1973+
if ns == TypeNS {
1974+
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
1975+
return Some(LexicalScopeBinding::Item(binding));
1976+
}
19811977
}
19821978
if ns == TypeNS && is_known_tool(ident.name) {
19831979
let binding = (Def::ToolMod, ty::Visibility::Public,
@@ -4018,7 +4014,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
40184014
} else {
40194015
// Items from the prelude
40204016
if !module.no_implicit_prelude {
4021-
names.extend(self.extern_prelude.iter().cloned());
4017+
names.extend(self.extern_prelude.iter().map(|(ident, _)| ident.name));
40224018
if let Some(prelude) = self.prelude {
40234019
add_module_candidates(prelude, &mut names);
40244020
}
@@ -4459,11 +4455,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
44594455

44604456
if self.session.rust_2018() {
44614457
let extern_prelude_names = self.extern_prelude.clone();
4462-
for &name in extern_prelude_names.iter() {
4463-
let ident = Ident::with_empty_ctxt(name);
4464-
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name,
4465-
ident.span)
4466-
{
4458+
for (ident, _) in extern_prelude_names.into_iter() {
4459+
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
4460+
ident.span) {
44674461
let crate_root = self.get_module(DefId {
44684462
krate: crate_id,
44694463
index: CRATE_DEF_INDEX,
@@ -4825,6 +4819,28 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
48254819
err.emit();
48264820
self.name_already_seen.insert(name, span);
48274821
}
4822+
4823+
fn extern_prelude_get(&mut self, ident: Ident, speculative: bool)
4824+
-> Option<&'a NameBinding<'a>> {
4825+
self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
4826+
if let Some(binding) = entry.extern_crate_item {
4827+
Some(binding)
4828+
} else {
4829+
let crate_id = if !speculative {
4830+
self.crate_loader.process_path_extern(ident.name, ident.span)
4831+
} else if let Some(crate_id) =
4832+
self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
4833+
crate_id
4834+
} else {
4835+
return None;
4836+
};
4837+
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
4838+
self.populate_module_if_necessary(&crate_root);
4839+
Some((crate_root, ty::Visibility::Public, ident.span, Mark::root())
4840+
.to_name_binding(self.arenas))
4841+
}
4842+
})
4843+
}
48284844
}
48294845

48304846
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {

src/librustc_resolve/macros.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -691,19 +691,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
691691
}
692692
}
693693
WhereToResolve::ExternPrelude => {
694-
if use_prelude && self.extern_prelude.contains(&ident.name) {
695-
let crate_id =
696-
self.crate_loader.process_path_extern(ident.name, ident.span);
697-
let crate_root =
698-
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
699-
self.populate_module_if_necessary(crate_root);
700-
701-
let binding = (crate_root, ty::Visibility::Public,
702-
ident.span, Mark::root()).to_name_binding(self.arenas);
703-
Ok((binding, Flags::PRELUDE, Flags::empty()))
704-
} else {
705-
Err(Determinacy::Determined)
694+
let mut result = Err(Determinacy::Determined);
695+
if use_prelude {
696+
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
697+
result = Ok((binding, Flags::PRELUDE, Flags::empty()));
698+
}
706699
}
700+
result
707701
}
708702
WhereToResolve::ToolPrelude => {
709703
if use_prelude && is_known_tool(ident.name) {

src/librustc_resolve/resolve_imports.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_data_structures::ptr_key::PtrKey;
2121
use rustc::ty;
2222
use rustc::lint::builtin::BuiltinLintDiagnostics;
2323
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
24-
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
24+
use rustc::hir::def_id::DefId;
2525
use rustc::hir::def::*;
2626
use rustc::session::DiagnosticMessageId;
2727
use rustc::util::nodemap::FxHashSet;
@@ -202,7 +202,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
202202
if !(
203203
ns == TypeNS &&
204204
!ident.is_path_segment_keyword() &&
205-
self.extern_prelude.contains(&ident.name)
205+
self.extern_prelude.contains_key(&ident.modern())
206206
) {
207207
// ... unless the crate name is not in the `extern_prelude`.
208208
return binding;
@@ -220,12 +220,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
220220
self.resolve_crate_root(ident)
221221
} else if
222222
ns == TypeNS &&
223-
!ident.is_path_segment_keyword() &&
224-
self.extern_prelude.contains(&ident.name)
223+
!ident.is_path_segment_keyword()
225224
{
226-
let crate_id =
227-
self.crate_loader.process_path_extern(ident.name, ident.span);
228-
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
225+
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
226+
let module = self.get_module(binding.def().def_id());
227+
self.populate_module_if_necessary(module);
228+
return Ok(binding);
229+
} else {
230+
return Err(Determined);
231+
}
229232
} else {
230233
return Err(Determined);
231234
};
@@ -738,10 +741,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
738741
let uniform_paths_feature = self.session.features_untracked().uniform_paths;
739742
for ((span, _, ns), results) in uniform_paths_canaries {
740743
let name = results.name;
741-
let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) {
742-
let crate_id =
743-
self.crate_loader.process_path_extern(name, span);
744-
Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX }))
744+
let external_crate = if ns == TypeNS {
745+
self.extern_prelude_get(Ident::with_empty_ctxt(name), true)
746+
.map(|binding| binding.def())
745747
} else {
746748
None
747749
};

src/librustc_typeck/check_unused.rs

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

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-pass
2+
// edition:2018
3+
4+
extern crate proc_macro;
5+
use proc_macro::TokenStream; // OK
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// compile-pass
2+
// compile-flags:--cfg my_feature
3+
4+
#![no_std]
5+
6+
#[cfg(my_feature)]
7+
extern crate std;
8+
9+
mod m {
10+
#[cfg(my_feature)]
11+
fn conditional() {
12+
std::vec::Vec::<u8>::new(); // OK
13+
}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// aux-build:two_macros.rs
2+
3+
mod n {
4+
extern crate two_macros;
5+
}
6+
7+
mod m {
8+
fn check() {
9+
two_macros::m!(); //~ ERROR failed to resolve. Use of undeclared type or module `two_macros`
10+
}
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0433]: failed to resolve. Use of undeclared type or module `two_macros`
2+
--> $DIR/extern-prelude-extern-crate-fail.rs:9:9
3+
|
4+
LL | two_macros::m!(); //~ ERROR failed to resolve. Use of undeclared type or module `two_macros`
5+
| ^^^^^^^^^^ Use of undeclared type or module `two_macros`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0433`.

0 commit comments

Comments
 (0)