Skip to content

Commit 58481c0

Browse files
authored
Rollup merge of #50665 - alexcrichton:fix-single-item-path-warnings, r=Manishearth
rustc: Fix `crate` lint for single-item paths This commit fixes recommending the `crate` prefix when migrating to 2018 for paths that look like `use foo;` or `use {bar, baz}` Closes #50660
2 parents 4d81fc8 + 43f6b96 commit 58481c0

File tree

5 files changed

+121
-34
lines changed

5 files changed

+121
-34
lines changed

src/librustc/lint/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ declare_lint! {
261261
}
262262

263263
declare_lint! {
264-
pub ABSOLUTE_PATH_STARTING_WITH_MODULE,
264+
pub ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
265265
Allow,
266266
"fully qualified paths that start with a module name \
267267
instead of `crate`, `self`, or an extern crate name"
@@ -328,7 +328,7 @@ impl LintPass for HardwiredLints {
328328
TYVAR_BEHIND_RAW_POINTER,
329329
ELIDED_LIFETIME_IN_PATH,
330330
BARE_TRAIT_OBJECT,
331-
ABSOLUTE_PATH_STARTING_WITH_MODULE,
331+
ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
332332
UNSTABLE_NAME_COLLISION,
333333
)
334334
}

src/librustc_lint/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extern crate rustc_target;
4040
extern crate syntax_pos;
4141

4242
use rustc::lint;
43-
use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE};
43+
use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE};
4444
use rustc::session;
4545
use rustc::util;
4646

@@ -282,7 +282,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
282282
// standard library, and thus should never be removed or changed to an error.
283283
},
284284
FutureIncompatibleInfo {
285-
id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE),
285+
id: LintId::of(ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE),
286286
reference: "issue TBD",
287287
edition: Some(Edition::Edition2018),
288288
},

src/librustc_resolve/lib.rs

+70-27
Original file line numberDiff line numberDiff line change
@@ -3232,6 +3232,7 @@ impl<'a> Resolver<'a> {
32323232
-> PathResult<'a> {
32333233
let mut module = None;
32343234
let mut allow_super = true;
3235+
let mut second_binding = None;
32353236

32363237
for (i, &ident) in path.iter().enumerate() {
32373238
debug!("resolve_path ident {} {:?}", i, ident);
@@ -3321,7 +3322,9 @@ impl<'a> Resolver<'a> {
33213322
.map(MacroBinding::binding)
33223323
} else {
33233324
match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
3325+
// we found a locally-imported or available item/module
33243326
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
3327+
// we found a local variable or type param
33253328
Some(LexicalScopeBinding::Def(def))
33263329
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
33273330
return PathResult::NonModule(PathResolution::with_unresolved_segments(
@@ -3334,13 +3337,22 @@ impl<'a> Resolver<'a> {
33343337

33353338
match binding {
33363339
Ok(binding) => {
3340+
if i == 1 {
3341+
second_binding = Some(binding);
3342+
}
33373343
let def = binding.def();
33383344
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
33393345
if let Some(next_module) = binding.module() {
33403346
module = Some(next_module);
33413347
} else if def == Def::Err {
33423348
return PathResult::NonModule(err_path_resolution());
33433349
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
3350+
self.lint_if_path_starts_with_module(
3351+
node_id,
3352+
path,
3353+
path_span,
3354+
second_binding,
3355+
);
33443356
return PathResult::NonModule(PathResolution::with_unresolved_segments(
33453357
def, path.len() - i - 1
33463358
));
@@ -3349,33 +3361,6 @@ impl<'a> Resolver<'a> {
33493361
format!("Not a module `{}`", ident),
33503362
is_last);
33513363
}
3352-
3353-
if let Some(id) = node_id {
3354-
if i == 1 && self.session.features_untracked().crate_in_paths
3355-
&& !self.session.rust_2018() {
3356-
let prev_name = path[0].name;
3357-
if prev_name == keywords::Extern.name() ||
3358-
prev_name == keywords::CrateRoot.name() {
3359-
let mut is_crate = false;
3360-
if let NameBindingKind::Import { directive: d, .. } = binding.kind {
3361-
if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
3362-
is_crate = true;
3363-
}
3364-
}
3365-
3366-
if !is_crate {
3367-
let diag = lint::builtin::BuiltinLintDiagnostics
3368-
::AbsPathWithModule(path_span);
3369-
self.session.buffer_lint_with_diagnostic(
3370-
lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE,
3371-
id, path_span,
3372-
"Absolute paths must start with `self`, `super`, \
3373-
`crate`, or an external crate name in the 2018 edition",
3374-
diag);
3375-
}
3376-
}
3377-
}
3378-
}
33793364
}
33803365
Err(Undetermined) => return PathResult::Indeterminate,
33813366
Err(Determined) => {
@@ -3408,9 +3393,67 @@ impl<'a> Resolver<'a> {
34083393
}
34093394
}
34103395

3396+
self.lint_if_path_starts_with_module(node_id, path, path_span, second_binding);
3397+
34113398
PathResult::Module(module.unwrap_or(self.graph_root))
34123399
}
34133400

3401+
fn lint_if_path_starts_with_module(&self,
3402+
id: Option<NodeId>,
3403+
path: &[Ident],
3404+
path_span: Span,
3405+
second_binding: Option<&NameBinding>) {
3406+
// In the 2018 edition this lint is a hard error, so nothing to do
3407+
if self.session.rust_2018() {
3408+
return
3409+
}
3410+
// In the 2015 edition there's no use in emitting lints unless the
3411+
// crate's already enabled the feature that we're going to suggest
3412+
if !self.session.features_untracked().crate_in_paths {
3413+
return
3414+
}
3415+
let id = match id {
3416+
Some(id) => id,
3417+
None => return,
3418+
};
3419+
let first_name = match path.get(0) {
3420+
Some(ident) => ident.name,
3421+
None => return,
3422+
};
3423+
3424+
// We're only interested in `use` paths which should start with
3425+
// `{{root}}` or `extern` currently.
3426+
if first_name != keywords::Extern.name() && first_name != keywords::CrateRoot.name() {
3427+
return
3428+
}
3429+
3430+
if let Some(part) = path.get(1) {
3431+
if part.name == keywords::Crate.name() {
3432+
return
3433+
}
3434+
}
3435+
3436+
// If the first element of our path was actually resolved to an
3437+
// `ExternCrate` (also used for `crate::...`) then no need to issue a
3438+
// warning, this looks all good!
3439+
if let Some(binding) = second_binding {
3440+
if let NameBindingKind::Import { directive: d, .. } = binding.kind {
3441+
if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
3442+
return
3443+
}
3444+
}
3445+
}
3446+
3447+
let diag = lint::builtin::BuiltinLintDiagnostics
3448+
::AbsPathWithModule(path_span);
3449+
self.session.buffer_lint_with_diagnostic(
3450+
lint::builtin::ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
3451+
id, path_span,
3452+
"Absolute paths must start with `self`, `super`, \
3453+
`crate`, or an external crate name in the 2018 edition",
3454+
diag);
3455+
}
3456+
34143457
// Resolve a local definition, potentially adjusting for closures.
34153458
fn adjust_local_def(&mut self,
34163459
ns: Namespace,

src/test/ui/edition-lint-paths.rs

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ pub mod foo {
1818
//~| WARN this was previously accepted
1919
use super::bar::Bar2;
2020
use crate::bar::Bar3;
21+
22+
use bar;
23+
//~^ ERROR Absolute
24+
//~| WARN this was previously accepted
25+
use crate::{bar as something_else};
26+
27+
use {Bar as SomethingElse, main};
28+
//~^ ERROR Absolute
29+
//~| WARN this was previously accepted
30+
//~| ERROR Absolute
31+
//~| WARN this was previously accepted
32+
33+
use crate::{Bar as SomethingElse2, main as another_main};
34+
35+
pub fn test() {
36+
}
2137
}
2238

2339

@@ -38,4 +54,5 @@ fn main() {
3854
let x = bar::Bar;
3955
let x = ::crate::bar::Bar;
4056
let x = self::bar::Bar;
57+
foo::test();
4158
}

src/test/ui/edition-lint-paths.stderr

+30-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,34 @@ LL | #![deny(absolute_path_starting_with_module)]
1313
= note: for more information, see issue TBD
1414

1515
error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
16-
--> $DIR/edition-lint-paths.rs:24:5
16+
--> $DIR/edition-lint-paths.rs:22:9
17+
|
18+
LL | use bar;
19+
| ^^^ help: use `crate`: `crate::bar`
20+
|
21+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
22+
= note: for more information, see issue TBD
23+
24+
error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
25+
--> $DIR/edition-lint-paths.rs:27:10
26+
|
27+
LL | use {Bar as SomethingElse, main};
28+
| ^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::Bar as SomethingElse`
29+
|
30+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
31+
= note: for more information, see issue TBD
32+
33+
error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
34+
--> $DIR/edition-lint-paths.rs:27:32
35+
|
36+
LL | use {Bar as SomethingElse, main};
37+
| ^^^^ help: use `crate`: `crate::main`
38+
|
39+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
40+
= note: for more information, see issue TBD
41+
42+
error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
43+
--> $DIR/edition-lint-paths.rs:40:5
1744
|
1845
LL | use bar::Bar;
1946
| ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
@@ -22,13 +49,13 @@ LL | use bar::Bar;
2249
= note: for more information, see issue TBD
2350

2451
error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
25-
--> $DIR/edition-lint-paths.rs:35:13
52+
--> $DIR/edition-lint-paths.rs:51:13
2653
|
2754
LL | let x = ::bar::Bar;
2855
| ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
2956
|
3057
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
3158
= note: for more information, see issue TBD
3259

33-
error: aborting due to 3 previous errors
60+
error: aborting due to 6 previous errors
3461

0 commit comments

Comments
 (0)