about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md1
-rw-r--r--compiler/rustc_lint/src/context.rs8
-rw-r--r--compiler/rustc_lint/src/levels.rs4
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs6
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/util.rs18
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_session/src/parse.rs9
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs30
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css5
-rw-r--r--src/librustdoc/html/static/js/search.js29
-rw-r--r--tests/rustdoc-gui/search-reexport.goml2
-rw-r--r--tests/rustdoc-gui/search-result-color.goml4
-rw-r--r--tests/ui/lint/lint-qualification.fixed21
-rw-r--r--tests/ui/lint/lint-qualification.rs1
-rw-r--r--tests/ui/lint/lint-qualification.stderr11
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed31
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs31
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr31
-rw-r--r--tests/ui/resolve/unused-qualifications-suggestion.stderr14
-rw-r--r--triagebot.toml2
22 files changed, 212 insertions, 58 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 3205b02e5c4..e8c79c573f9 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -92,7 +92,6 @@ Cargo
 -----
 - [Allow named debuginfo options in `Cargo.toml`.](https://github.com/rust-lang/cargo/pull/11958/)
 - [Add `workspace_default_members` to the output of `cargo metadata`.](https://github.com/rust-lang/cargo/pull/11978/)
-- [`cargo add` now considers `rust-version` when selecting packages.](https://github.com/rust-lang/cargo/pull/12078/)
 - [Automatically inherit workspace fields when running `cargo new`/`cargo init`.](https://github.com/rust-lang/cargo/pull/12069/)
 
 <a id="1.71.0-Rustdoc"></a>
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/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index c9ee2da6fdf..0c80141a756 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -978,6 +978,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     /// Returns `true` if the lint's feature is enabled.
     // FIXME only emit this once for each attribute, instead of repeating it 4 times for
     // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
+    #[track_caller]
     fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
         if let Some(feature) = lint_id.lint.feature_gate {
             if !self.sess.features_untracked().enabled(feature) {
@@ -1015,6 +1016,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub(crate) fn struct_lint(
         &self,
         lint: &'static Lint,
@@ -1028,6 +1030,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
     }
 
+    #[track_caller]
     pub fn emit_spanned_lint(
         &self,
         lint: &'static Lint,
@@ -1040,6 +1043,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         });
     }
 
+    #[track_caller]
     pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) {
         let (level, src) = self.lint_level(lint);
         struct_lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
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_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 20230217afc..6ce1ad8f43e 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -278,6 +278,7 @@ pub fn explain_lint_level_source(
 ///     //          ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default
 /// )
 /// ```
+#[track_caller]
 pub fn struct_lint_level(
     sess: &Session,
     lint: &'static Lint,
@@ -291,6 +292,7 @@ pub fn struct_lint_level(
 ) {
     // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
     // the "real" work.
+    #[track_caller]
     fn struct_lint_level_impl(
         sess: &Session,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8bb13edbe95..1a23fa80210 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1860,6 +1860,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
     /// typically generated by `#[derive(LintDiagnostic)]`).
+    #[track_caller]
     pub fn emit_spanned_lint(
         self,
         lint: &'static Lint,
@@ -1880,6 +1881,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_lint_hir(
         self,
         lint: &'static Lint,
@@ -1896,6 +1898,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
     /// generated by `#[derive(LintDiagnostic)]`).
+    #[track_caller]
     pub fn emit_lint(
         self,
         lint: &'static Lint,
@@ -1911,6 +1914,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_lint_node(
         self,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b4852ab8881..553b76cad4e 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -19,7 +19,7 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_macros::HashStable;
 use rustc_session::Limit;
 use rustc_span::sym;
-use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
+use rustc_target::abi::{Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::{fmt, iter};
@@ -1085,7 +1085,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
-        match needs_drop_components(self, &tcx.data_layout) {
+        match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
             Ok(components) => {
                 let query_ty = match *components {
@@ -1118,7 +1118,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
-        match needs_drop_components(self, &tcx.data_layout) {
+        match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
             Ok(components) => {
                 let query_ty = match *components {
@@ -1278,10 +1278,10 @@ impl<'tcx> ExplicitSelf<'tcx> {
 /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
 /// this type always needs drop.
 pub fn needs_drop_components<'tcx>(
+    tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
-    target_layout: &TargetDataLayout,
 ) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
-    match ty.kind() {
+    match *ty.kind() {
         ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
         | ty::Bool
@@ -1303,11 +1303,11 @@ pub fn needs_drop_components<'tcx>(
 
         ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
 
-        ty::Slice(ty) => needs_drop_components(*ty, target_layout),
+        ty::Slice(ty) => needs_drop_components(tcx, ty),
         ty::Array(elem_ty, size) => {
-            match needs_drop_components(*elem_ty, target_layout) {
+            match needs_drop_components(tcx, elem_ty) {
                 Ok(v) if v.is_empty() => Ok(v),
-                res => match size.try_to_bits(target_layout.pointer_size) {
+                res => match size.try_to_target_usize(tcx) {
                     // Arrays of size zero don't need drop, even if their element
                     // type does.
                     Some(0) => Ok(SmallVec::new()),
@@ -1321,7 +1321,7 @@ pub fn needs_drop_components<'tcx>(
         }
         // If any field needs drop, then the whole tuple does.
         ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| {
-            acc.extend(needs_drop_components(elem, target_layout)?);
+            acc.extend(needs_drop_components(tcx, elem)?);
             Ok(acc)
         }),
 
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/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 194f7201ff3..d5326df9ad9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -117,6 +117,7 @@ pub fn feature_err_issue(
 /// Construct a future incompatibility diagnostic for a feature gate.
 ///
 /// This diagnostic is only a warning and *does not cause compilation to fail*.
+#[track_caller]
 pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
     feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
 }
@@ -129,6 +130,7 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st
 /// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
 #[allow(rustc::diagnostic_outside_of_impl)]
 #[allow(rustc::untranslatable_diagnostic)]
+#[track_caller]
 pub fn feature_warn_issue(
     sess: &ParseSess,
     feature: Symbol,
@@ -351,6 +353,7 @@ impl ParseSess {
         self.create_warning(warning).emit()
     }
 
+    #[track_caller]
     pub fn create_note<'a>(
         &'a self,
         note: impl IntoDiagnostic<'a, Noted>,
@@ -358,10 +361,12 @@ impl ParseSess {
         note.into_diagnostic(&self.span_diagnostic)
     }
 
+    #[track_caller]
     pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
         self.create_note(note).emit()
     }
 
+    #[track_caller]
     pub fn create_fatal<'a>(
         &'a self,
         fatal: impl IntoDiagnostic<'a, !>,
@@ -369,6 +374,7 @@ impl ParseSess {
         fatal.into_diagnostic(&self.span_diagnostic)
     }
 
+    #[track_caller]
     pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
         self.create_fatal(fatal).emit()
     }
@@ -383,16 +389,19 @@ impl ParseSess {
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.span_diagnostic.struct_warn(msg)
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
         self.span_diagnostic.struct_fatal(msg)
     }
 
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_diagnostic<G: EmissionGuarantee>(
         &self,
         msg: impl Into<DiagnosticMessage>,
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 3e6dfc1304f..e173bba49be 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -96,7 +96,7 @@ where
                 return Some(Err(AlwaysRequiresDrop));
             }
 
-            let components = match needs_drop_components(ty, &tcx.data_layout) {
+            let components = match needs_drop_components(tcx, ty) {
                 Err(e) => return Some(Err(e)),
                 Ok(components) => components,
             };
@@ -160,7 +160,7 @@ where
                             queue_type(self, required);
                         }
                     }
-                    ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
+                    ty::Alias(..) | ty::Array(..) | ty::Placeholder(_) | ty::Param(_) => {
                         if ty == component {
                             // Return the type to the caller: they may be able
                             // to normalize further than we can.
@@ -172,7 +172,31 @@ where
                             queue_type(self, component);
                         }
                     }
-                    _ => return Some(Err(AlwaysRequiresDrop)),
+
+                    ty::Foreign(_) | ty::Dynamic(..) => {
+                        return Some(Err(AlwaysRequiresDrop));
+                    }
+
+                    ty::Bool
+                    | ty::Char
+                    | ty::Int(_)
+                    | ty::Uint(_)
+                    | ty::Float(_)
+                    | ty::Str
+                    | ty::Slice(_)
+                    | ty::Ref(..)
+                    | ty::RawPtr(..)
+                    | ty::FnDef(..)
+                    | ty::FnPtr(..)
+                    | ty::Tuple(_)
+                    | ty::Bound(..)
+                    | ty::GeneratorWitness(..)
+                    | ty::GeneratorWitnessMIR(..)
+                    | ty::Never
+                    | ty::Infer(_)
+                    | ty::Error(_) => {
+                        bug!("unexpected type returned by `needs_drop_components`: {component}")
+                    }
                 }
             }
         }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 9209915895a..94e778406f8 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -888,7 +888,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	justify-content: start;
 	flex: 3;
 }
-.search-results .result-name span.alias {
+.search-results .result-name .alias {
 	color: var(--search-results-alias-color);
 }
 .search-results .result-name .grey {
@@ -904,6 +904,9 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	max-width: calc(100% - var(--search-typename-width));
 	display: inline-block;
 }
+.search-results .result-name .path > * {
+	display: inline;
+}
 
 .popover {
 	position: absolute;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 51d8e81ca86..42088e73554 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2108,29 +2108,22 @@ function initSearch(rawSearchIndex) {
                 const resultName = document.createElement("div");
                 resultName.className = "result-name";
 
-                if (item.is_alias) {
-                    const alias = document.createElement("span");
-                    alias.className = "alias";
-
-                    const bold = document.createElement("b");
-                    bold.innerText = item.alias;
-                    alias.appendChild(bold);
-
-                    alias.insertAdjacentHTML(
-                        "beforeend",
-                        "<i class=\"grey\">&nbsp;- see&nbsp;</i>");
+                resultName.insertAdjacentHTML(
+                    "beforeend",
+                    `<span class="typename">${typeName}</span>`);
+                link.appendChild(resultName);
 
-                    resultName.appendChild(alias);
+                let alias = " ";
+                if (item.is_alias) {
+                    alias = ` <div class="alias">\
+<b>${item.alias}</b><i class="grey">&nbsp;- see&nbsp;</i>\
+</div>`;
                 }
-
                 resultName.insertAdjacentHTML(
                     "beforeend",
-                    `\
-<span class="typename">${typeName}</span>\
-<div class="path">\
- ${item.displayPath}<span class="${type}">${name}</span>\
+                    `<div class="path">${alias}\
+${item.displayPath}<span class="${type}">${name}</span>\
 </div>`);
-                link.appendChild(resultName);
 
                 const description = document.createElement("div");
                 description.className = "desc";
diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml
index 6ea6d53e287..b9d2c8f15ce 100644
--- a/tests/rustdoc-gui/search-reexport.goml
+++ b/tests/rustdoc-gui/search-reexport.goml
@@ -26,7 +26,7 @@ write: (".search-input", "AliasForTheStdReexport")
 wait-for: "//a[@class='result-import']"
 assert-text: (
     "a.result-import .result-name",
-    "AliasForTheStdReexport - see re-export test_docs::TheStdReexport",
+    "re-export AliasForTheStdReexport - see test_docs::TheStdReexport",
 )
 // Same thing again, we click on it to ensure the background is once again set as expected.
 click: "//a[@class='result-import']"
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index 7a7785fd9ac..f9f81c5ba04 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -368,8 +368,8 @@ define-function: (
         // Waiting for the search results to appear...
         wait-for: "#search-tabs"
         // Checking that the colors for the alias element are the ones expected.
-        assert-css: (".result-name > .alias", {"color": |alias|})
-        assert-css: (".result-name > .alias > .grey", {"color": |grey|})
+        assert-css: (".result-name .path .alias", {"color": |alias|})
+        assert-css: (".result-name .path .alias > .grey", {"color": |grey|})
         // Leave the search results to prevent reloading with an already filled search input.
         press-key: "Escape"
     },
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<str> for A {
+    //~^ ERROR unnecessary qualification
+    type Output = ();
+    fn index(&self, _: str) -> &Self::Output {
+        &()
+    }
+}
+
+mod inner {
+    pub trait Trait<T> {}
+}
+
+// the import needs to be here for the lint to show up
+#[allow(unused_imports)]
+use inner::Trait;
+
+impl Trait<u8> 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<str> for A {
+    //~^ ERROR unnecessary qualification
+    type Output = ();
+    fn index(&self, _: str) -> &Self::Output {
+        &()
+    }
+}
+
+mod inner {
+    pub trait Trait<T> {}
+}
+
+// the import needs to be here for the lint to show up
+#[allow(unused_imports)]
+use inner::Trait;
+
+impl inner::Trait<u8> 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<str> 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<str> for A {
+LL + impl Index<str> for A {
+   |
+
+error: unnecessary qualification
+  --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6
+   |
+LL | impl inner::Trait<u8> for () {}
+   |      ^^^^^^^^^^^^^^^^
+   |
+help: remove the unnecessary path segments
+   |
+LL - impl inner::Trait<u8> for () {}
+LL + impl Trait<u8> 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
 
diff --git a/triagebot.toml b/triagebot.toml
index 1a435ff074e..cc26c3b3e7b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -457,7 +457,7 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
 
 [mentions."compiler/rustc_smir"]
 message = "This PR changes Stable MIR"
-cc = ["@oli-obk", "@celinval"]
+cc = ["@oli-obk", "@celinval", "@spastorino"]
 
 [mentions."compiler/rustc_target/src/spec"]
 message = """