diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 6522e449386..7c701fd4fe1 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -956,11 +956,11 @@ pub trait LintContext: Sized { db.span_note(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace)); db.span_note(private_item_span, "but the private item here shadows it".to_owned()); } - BuiltinLintDiagnostics::UnusedQualifications { path_span, unqualified_path } => { + BuiltinLintDiagnostics::UnusedQualifications { removal_span } => { db.span_suggestion_verbose( - path_span, - "replace it with the unqualified path", - unqualified_path, + removal_span, + "remove the unnecessary path segments", + "", Applicability::MachineApplicable ); } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f6ffd46b1fe..10ebe29dfce 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -551,10 +551,8 @@ pub enum BuiltinLintDiagnostics { private_item_span: Span, }, UnusedQualifications { - /// The span of the unnecessarily-qualified path. - path_span: Span, - /// The replacement unqualified path. - unqualified_path: Ident, + /// The span of the unnecessarily-qualified path to remove. + removal_span: Span, }, } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 846a1ffe09b..05128a51016 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3911,8 +3911,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate { + let last_segment = *path.last().unwrap(); let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { + match self.resolve_path(&[last_segment], Some(ns), None) { PathResult::NonModule(path_res) => path_res.expect_full_res(), PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() @@ -3928,8 +3929,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { finalize.path_span, "unnecessary qualification", lint::BuiltinLintDiagnostics::UnusedQualifications { - path_span: finalize.path_span, - unqualified_path: path.last().unwrap().ident + removal_span: finalize.path_span.until(last_segment.ident.span), } ) } diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed new file mode 100644 index 00000000000..c1449301362 --- /dev/null +++ b/tests/ui/lint/lint-qualification.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![deny(unused_qualifications)] +#![allow(deprecated)] + +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + bar(); //~ ERROR: unnecessary qualification + bar(); + + let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345 + + macro_rules! m { () => { + $crate::foo::bar(); // issue #37357 + ::foo::bar(); // issue #38682 + } } + m!(); +} diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs index 0cace0ca035..80904303559 100644 --- a/tests/ui/lint/lint-qualification.rs +++ b/tests/ui/lint/lint-qualification.rs @@ -1,3 +1,4 @@ +// run-rustfix #![deny(unused_qualifications)] #![allow(deprecated)] diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index d09cb78c4f0..90a06bc6cbe 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -1,18 +1,19 @@ error: unnecessary qualification - --> $DIR/lint-qualification.rs:10:5 + --> $DIR/lint-qualification.rs:11:5 | LL | foo::bar(); | ^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-qualification.rs:1:9 + --> $DIR/lint-qualification.rs:2:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); | -LL | bar(); - | ~~~ error: aborting due to previous error diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed new file mode 100644 index 00000000000..e730f94660b --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +#![deny(unused_qualifications)] +#![feature(unsized_fn_params)] + +#[allow(unused_imports)] +use std::ops; +use std::ops::Index; + +pub struct A; + +impl Index for A { + //~^ ERROR unnecessary qualification + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + +mod inner { + pub trait Trait {} +} + +// the import needs to be here for the lint to show up +#[allow(unused_imports)] +use inner::Trait; + +impl Trait for () {} +//~^ ERROR unnecessary qualification + +fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs new file mode 100644 index 00000000000..641c892e3de --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -0,0 +1,31 @@ +// run-rustfix + +#![deny(unused_qualifications)] +#![feature(unsized_fn_params)] + +#[allow(unused_imports)] +use std::ops; +use std::ops::Index; + +pub struct A; + +impl ops::Index for A { + //~^ ERROR unnecessary qualification + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + +mod inner { + pub trait Trait {} +} + +// the import needs to be here for the lint to show up +#[allow(unused_imports)] +use inner::Trait; + +impl inner::Trait for () {} +//~^ ERROR unnecessary qualification + +fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr new file mode 100644 index 00000000000..d9c7fd21871 --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -0,0 +1,31 @@ +error: unnecessary qualification + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:12:6 + | +LL | impl ops::Index for A { + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:3:9 + | +LL | #![deny(unused_qualifications)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: remove the unnecessary path segments + | +LL - impl ops::Index for A { +LL + impl Index for A { + | + +error: unnecessary qualification + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6 + | +LL | impl inner::Trait for () {} + | ^^^^^^^^^^^^^^^^ + | +help: remove the unnecessary path segments + | +LL - impl inner::Trait for () {} +LL + impl Trait for () {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/unused-qualifications-suggestion.stderr b/tests/ui/resolve/unused-qualifications-suggestion.stderr index c8e91e07295..e3dac37fc6e 100644 --- a/tests/ui/resolve/unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/unused-qualifications-suggestion.stderr @@ -9,10 +9,11 @@ note: the lint level is defined here | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); | -LL | bar(); - | ~~~ error: unnecessary qualification --> $DIR/unused-qualifications-suggestion.rs:21:5 @@ -20,10 +21,11 @@ error: unnecessary qualification LL | baz::qux::quux(); | ^^^^^^^^^^^^^^ | -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - baz::qux::quux(); +LL + quux(); | -LL | quux(); - | ~~~~ error: aborting due to 2 previous errors