Skip to content

Commit eab91ba

Browse files
committed
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
1 parent fe63e47 commit eab91ba

File tree

3 files changed

+115
-30
lines changed

3 files changed

+115
-30
lines changed

src/librustc_resolve/lib.rs

+68-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);
@@ -3334,13 +3335,22 @@ impl<'a> Resolver<'a> {
33343335

33353336
match binding {
33363337
Ok(binding) => {
3338+
if i == 1 {
3339+
second_binding = Some(binding);
3340+
}
33373341
let def = binding.def();
33383342
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
33393343
if let Some(next_module) = binding.module() {
33403344
module = Some(next_module);
33413345
} else if def == Def::Err {
33423346
return PathResult::NonModule(err_path_resolution());
33433347
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
3348+
self.lint_if_path_starts_with_module(
3349+
node_id,
3350+
path,
3351+
path_span,
3352+
second_binding,
3353+
);
33443354
return PathResult::NonModule(PathResolution::with_unresolved_segments(
33453355
def, path.len() - i - 1
33463356
));
@@ -3349,33 +3359,6 @@ impl<'a> Resolver<'a> {
33493359
format!("Not a module `{}`", ident),
33503360
is_last);
33513361
}
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-
}
33793362
}
33803363
Err(Undetermined) => return PathResult::Indeterminate,
33813364
Err(Determined) => {
@@ -3408,9 +3391,67 @@ impl<'a> Resolver<'a> {
34083391
}
34093392
}
34103393

3394+
self.lint_if_path_starts_with_module(node_id, path, path_span, second_binding);
3395+
34113396
PathResult::Module(module.unwrap_or(self.graph_root))
34123397
}
34133398

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