Skip to content

Don't lint non-extern-prelude extern crate's in Rust 2018. #54650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use syntax::parse;
use syntax::parse::ParseSess;
use syntax::{ast, source_map};
use syntax::feature_gate::AttributeType;
use syntax_pos::{MultiSpan, Span};
use syntax_pos::{MultiSpan, Span, symbol::Symbol};
use util::profiling::SelfProfiler;

use rustc_target::spec::PanicStrategy;
Expand Down Expand Up @@ -168,6 +168,10 @@ pub struct Session {

/// Cap lint level specified by a driver specifically.
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,

/// All the crate names specified with `--extern`, and the builtin ones.
/// Starting with the Rust 2018 edition, absolute paths resolve in this set.
pub extern_prelude: FxHashSet<Symbol>,
}

pub struct PerfStats {
Expand Down Expand Up @@ -1126,6 +1130,18 @@ pub fn build_session_(
CguReuseTracker::new_disabled()
};


let mut extern_prelude: FxHashSet<Symbol> =
sopts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();

// HACK(eddyb) this ignores the `no_{core,std}` attributes.
// FIXME(eddyb) warn (somewhere) if core/std is used with `no_{core,std}`.
// if !attr::contains_name(&krate.attrs, "no_core") {
// if !attr::contains_name(&krate.attrs, "no_std") {
extern_prelude.insert(Symbol::intern("core"));
extern_prelude.insert(Symbol::intern("std"));
extern_prelude.insert(Symbol::intern("meta"));

let sess = Session {
target: target_cfg,
host,
Expand Down Expand Up @@ -1201,6 +1217,7 @@ pub fn build_session_(
has_global_allocator: Once::new(),
has_panic_handler: Once::new(),
driver_lint_caps: FxHashMap(),
extern_prelude,
};

validate_commandline_args_with_session_available(&sess);
Expand Down
20 changes: 3 additions & 17 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,6 @@ pub struct Resolver<'a, 'b: 'a> {
graph_root: Module<'a>,

prelude: Option<Module<'a>>,
extern_prelude: FxHashSet<Name>,

/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
Expand Down Expand Up @@ -1663,17 +1662,6 @@ 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();

// HACK(eddyb) this ignore the `no_{core,std}` attributes.
// FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
// if !attr::contains_name(&krate.attrs, "no_core") {
// if !attr::contains_name(&krate.attrs, "no_std") {
extern_prelude.insert(Symbol::intern("core"));
extern_prelude.insert(Symbol::intern("std"));
extern_prelude.insert(Symbol::intern("meta"));

let mut invocations = FxHashMap();
invocations.insert(Mark::root(),
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
Expand All @@ -1692,7 +1680,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// AST.
graph_root,
prelude: None,
extern_prelude,

has_self: FxHashSet(),
field_names: FxHashMap(),
Expand Down Expand Up @@ -1963,7 +1950,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {

if !module.no_implicit_prelude {
// `record_used` means that we don't try to load crates during speculative resolution
if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
if record_used && ns == TypeNS && self.session.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);
Expand Down Expand Up @@ -3955,7 +3942,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.session.extern_prelude.iter().cloned());
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
Expand Down Expand Up @@ -4401,8 +4388,7 @@ 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() {
for &name in &self.session.extern_prelude {
let ident = Ident::with_empty_ctxt(name);
match self.crate_loader.maybe_process_path_extern(name, ident.span) {
Some(crate_id) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
result
}
WhereToResolve::ExternPrelude => {
if use_prelude && self.extern_prelude.contains(&ident.name) {
if use_prelude && self.session.extern_prelude.contains(&ident.name) {
let crate_id =
self.crate_loader.process_path_extern(ident.name, ident.span);
let crate_root =
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
if !(
ns == TypeNS &&
!ident.is_path_segment_keyword() &&
self.extern_prelude.contains(&ident.name)
self.session.extern_prelude.contains(&ident.name)
) {
// ... unless the crate name is not in the `extern_prelude`.
return binding;
Expand All @@ -218,7 +218,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
} else if
ns == TypeNS &&
!ident.is_path_segment_keyword() &&
self.extern_prelude.contains(&ident.name)
self.session.extern_prelude.contains(&ident.name)
{
let crate_id =
self.crate_loader.process_path_extern(ident.name, ident.span);
Expand Down Expand Up @@ -735,7 +735,7 @@ 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 external_crate = if ns == TypeNS && self.session.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 }))
Expand Down
16 changes: 9 additions & 7 deletions src/librustc_typeck/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,13 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
});

for extern_crate in &crates_to_lint {
assert!(extern_crate.def_id.is_local());
let id = tcx.hir.as_local_node_id(extern_crate.def_id).unwrap();
let item = tcx.hir.expect_item(id);

// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if extern_crate.warn_if_unused {
if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
let id = tcx.hir.hir_to_node_id(hir_id);
let msg = "unused extern crate";
tcx.struct_span_lint_node(lint, id, span, msg)
.span_suggestion_short_with_applicability(
Expand All @@ -157,6 +155,13 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
continue;
}

// 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.sess.extern_prelude.contains(&orig_name) {
continue;
}

// If the extern crate has any attributes, they may have funky
// semantics we can't faithfully represent using `use` (most
// notably `#[macro_use]`). Ignore it.
Expand All @@ -165,9 +170,6 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
}

// Otherwise, we can convert it into a `use` of some kind.
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
let id = tcx.hir.hir_to_node_id(hir_id);
let item = tcx.hir.expect_item(id);
let msg = "`extern crate` is not idiomatic in the new edition";
let help = format!(
"convert it to a `{}`",
Expand Down
22 changes: 4 additions & 18 deletions src/test/ui-fulldeps/unnecessary-extern-crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,23 @@ extern crate alloc as x;
//~^ ERROR unused extern crate
//~| HELP remove

extern crate proc_macro;

#[macro_use]
extern crate test;

pub extern crate test as y;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub use`

pub extern crate libc;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub use`

pub(crate) extern crate libc as a;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(crate) use`

crate extern crate libc as b;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `crate use`

mod foo {
pub(in crate::foo) extern crate libc as c;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(in crate::foo) use`

pub(super) extern crate libc as d;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(super) use`

extern crate alloc;
//~^ ERROR unused extern crate
Expand All @@ -57,12 +47,8 @@ mod foo {
//~| HELP remove

pub extern crate test;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it

pub extern crate test as y;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it

mod bar {
extern crate alloc;
Expand All @@ -74,8 +60,6 @@ mod foo {
//~| HELP remove

pub(in crate::foo::bar) extern crate libc as e;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(in crate::foo::bar) use`

fn dummy() {
unsafe {
Expand All @@ -96,4 +80,6 @@ mod foo {
fn main() {
unsafe { a::getpid(); }
unsafe { b::getpid(); }

proc_macro::TokenStream::new();
}
64 changes: 5 additions & 59 deletions src/test/ui-fulldeps/unnecessary-extern-crate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,83 +16,29 @@ error: unused extern crate
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:26:1
|
LL | pub extern crate test as y;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:30:1
|
LL | pub extern crate libc;
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:34:1
|
LL | pub(crate) extern crate libc as a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:38:1
|
LL | crate extern crate libc as b;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:43:5
|
LL | pub(in crate::foo) extern crate libc as c;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:47:5
|
LL | pub(super) extern crate libc as d;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(super) use`

error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:51:5
--> $DIR/unnecessary-extern-crate.rs:41:5
|
LL | extern crate alloc;
| ^^^^^^^^^^^^^^^^^^^ help: remove it

error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:55:5
--> $DIR/unnecessary-extern-crate.rs:45:5
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:59:5
|
LL | pub extern crate test;
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:63:5
|
LL | pub extern crate test as y;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`

error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:68:9
--> $DIR/unnecessary-extern-crate.rs:54:9
|
LL | extern crate alloc;
| ^^^^^^^^^^^^^^^^^^^ help: remove it

error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:72:9
--> $DIR/unnecessary-extern-crate.rs:58:9
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it

error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:76:9
|
LL | pub(in crate::foo::bar) extern crate libc as e;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo::bar) use`

error: aborting due to 15 previous errors
error: aborting due to 6 previous errors

6 changes: 6 additions & 0 deletions src/test/ui/rust-2018/remove-extern-crate.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate

#![feature(alloc)]
#![warn(rust_2018_idioms)]


Expand All @@ -22,11 +23,16 @@ use remove_extern_crate;
#[macro_use]
extern crate remove_extern_crate as something_else;

// Shouldn't suggest changing to `use`, as the `alloc`
// crate is not in the extern prelude - see #54381.
extern crate alloc;

fn main() {
another_name::mem::drop(3);
another::foo();
remove_extern_crate::foo!();
bar!();
alloc::vec![5];
}

mod another {
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/rust-2018/remove-extern-crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate

#![feature(alloc)]
#![warn(rust_2018_idioms)]

extern crate core;
Expand All @@ -22,11 +23,16 @@ use remove_extern_crate;
#[macro_use]
extern crate remove_extern_crate as something_else;

// Shouldn't suggest changing to `use`, as the `alloc`
// crate is not in the extern prelude - see #54381.
extern crate alloc;

fn main() {
another_name::mem::drop(3);
another::foo();
remove_extern_crate::foo!();
bar!();
alloc::vec![5];
}

mod another {
Expand Down
Loading