about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-25 17:14:33 +0000
committerMichael Goulet <michael@errs.io>2025-02-13 05:45:53 +0000
commit72b4df3772a6c2cae8d9cf7ae618c010c10131b2 (patch)
tree7c2d611b8fce4d6776b7579df0a65d8078399290
parent2189908170f86809b7de5275dcde0cf828c16b37 (diff)
downloadrust-72b4df3772a6c2cae8d9cf7ae618c010c10131b2.tar.gz
rust-72b4df3772a6c2cae8d9cf7ae618c010c10131b2.zip
Implement lint for definition site item shadowing too
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs45
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs9
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs42
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs2
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr28
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs3
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr46
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor.rs2
-rw-r--r--tests/ui/methods/supertrait-shadowing/common-ancestor.stderr25
-rw-r--r--tests/ui/methods/supertrait-shadowing/definition-site.rs18
-rw-r--r--tests/ui/methods/supertrait-shadowing/definition-site.stderr34
-rw-r--r--tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs2
-rw-r--r--tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr31
15 files changed, 296 insertions, 25 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 7344ea01fb2..5560d087e96 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -506,6 +506,12 @@ hir_analysis_specialization_trait = implementing `rustc_specialization_trait` tr
 
 hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
+hir_analysis_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits}
+
+hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item
+
+hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
+
 hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
     .note = this item must mention the opaque type in its signature in order to be able to register hidden types
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1689437ffb0..4218f4ef0c1 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,6 +12,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{AmbigArg, ItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
+use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
 use rustc_macros::LintDiagnostic;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
@@ -388,7 +389,12 @@ fn check_trait_item<'tcx>(
         hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
         _ => (None, trait_item.span),
     };
+
     check_dyn_incompatible_self_trait_by_name(tcx, trait_item);
+
+    // Check that an item definition in a subtrait is shadowing a supertrait item.
+    lint_item_shadowing_supertrait_item(tcx, def_id);
+
     let mut res = check_associated_item(tcx, def_id, span, method_sig);
 
     if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
@@ -898,6 +904,45 @@ fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitI
     }
 }
 
+fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {
+    let item_name = tcx.item_name(trait_item_def_id.to_def_id());
+    let trait_def_id = tcx.local_parent(trait_item_def_id);
+
+    let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id())
+        .skip(1)
+        .flat_map(|supertrait_def_id| {
+            tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name)
+        })
+        .collect();
+    if !shadowed.is_empty() {
+        let shadowee = if let [shadowed] = shadowed[..] {
+            errors::SupertraitItemShadowee::Labeled {
+                span: tcx.def_span(shadowed.def_id),
+                supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()),
+            }
+        } else {
+            let (traits, spans): (Vec<_>, Vec<_>) = shadowed
+                .iter()
+                .map(|item| {
+                    (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id))
+                })
+                .unzip();
+            errors::SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() }
+        };
+
+        tcx.emit_node_span_lint(
+            SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
+            tcx.local_def_id_to_hir_id(trait_item_def_id),
+            tcx.def_span(trait_item_def_id),
+            errors::SupertraitItemShadowing {
+                item: item_name,
+                subtrait: tcx.item_name(trait_def_id.to_def_id()),
+                shadowee,
+            },
+        );
+    }
+}
+
 fn check_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_item: &'tcx hir::ImplItem<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 1574506de60..14ea10461cb 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -3,7 +3,8 @@
 use rustc_abi::ExternAbi;
 use rustc_errors::codes::*;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
+    Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
+    MultiSpan,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -1733,3 +1734,28 @@ pub(crate) struct RegisterTypeUnstable<'a> {
     pub span: Span,
     pub ty: Ty<'a>,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_supertrait_item_shadowing)]
+pub(crate) struct SupertraitItemShadowing {
+    pub item: Symbol,
+    pub subtrait: Symbol,
+    #[subdiagnostic]
+    pub shadowee: SupertraitItemShadowee,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum SupertraitItemShadowee {
+    #[note(hir_analysis_supertrait_item_shadowee)]
+    Labeled {
+        #[primary_span]
+        span: Span,
+        supertrait: Symbol,
+    },
+    #[note(hir_analysis_supertrait_item_multiple_shadowee)]
+    Several {
+        #[primary_span]
+        spans: MultiSpan,
+        traits: DiagSymbolList,
+    },
+}
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 0ed7fb37211..8fb425ff0c9 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -143,9 +143,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let method_sig = ty::Binder::dummy(method_sig);
 
         // Make sure nobody calls `drop()` explicitly.
-        self.enforce_illegal_method_limitations(pick);
+        self.check_for_illegal_method_calls(pick);
 
-        self.enforce_shadowed_supertrait_items(pick, segment);
+        // Lint when an item is shadowing a supertrait item.
+        self.lint_shadowed_supertrait_items(pick, segment);
 
         // Add any trait/regions obligations specified on the method's type parameters.
         // We won't add these if we encountered an illegal sized bound, so that we can use
@@ -660,7 +661,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             })
     }
 
-    fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
+    fn check_for_illegal_method_calls(&self, pick: &probe::Pick<'_>) {
         // Disallow calls to the method `drop` defined in the `Drop` trait.
         if let Some(trait_def_id) = pick.item.trait_container(self.tcx) {
             if let Err(e) = callee::check_legal_trait_for_method_call(
@@ -676,7 +677,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         }
     }
 
-    fn enforce_shadowed_supertrait_items(
+    fn lint_shadowed_supertrait_items(
         &self,
         pick: &probe::Pick<'_>,
         segment: &hir::PathSegment<'tcx>,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 55fa7d9d86c..10bf4ec77ed 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -101,6 +101,7 @@ declare_lint_pass! {
         SINGLE_USE_LIFETIMES,
         SOFT_UNSTABLE,
         STABLE_FEATURES,
+        SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
         SUPERTRAIT_ITEM_SHADOWING_USAGE,
         TAIL_EXPR_DROP_ORDER,
         TEST_UNSTABLE_LINT,
@@ -4924,7 +4925,7 @@ declare_lint! {
     ///
     /// ### Example
     ///
-    /// ```rust
+    /// ```rust,compile_fail
     /// #![feature(supertrait_item_shadowing)]
     /// #![deny(supertrait_item_shadowing_usage)]
     ///
@@ -4960,6 +4961,45 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `supertrait_item_shadowing_definition` lint detects when the
+    /// definition of an item that is provided by both a subtrait and
+    /// supertrait is shadowed, preferring the subtrait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(supertrait_item_shadowing)]
+    /// #![deny(supertrait_item_shadowing_definition)]
+    ///
+    /// trait Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Upstream for T {}
+    ///
+    /// trait Downstream: Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Downstream for T {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// RFC 3624 specified a heuristic in which a supertrait item would be
+    /// shadowed by a subtrait item when ambiguity occurs during item
+    /// selection. In order to mitigate side-effects of this happening
+    /// silently, this lint detects these cases when users want to deny them
+    /// or fix their trait definitions.
+    pub SUPERTRAIT_ITEM_SHADOWING_DEFINITION,
+    // FIXME(supertrait_item_shadowing): It is not decided if this should
+    // warn by default at the usage site.
+    Allow,
+    "detects when a supertrait item is shadowed by a subtrait item",
+    @feature_gate = supertrait_item_shadowing;
+}
+
+declare_lint! {
     /// The `ptr_to_integer_transmute_in_consts` lint detects pointer to integer
     /// transmute in const functions and associated constants.
     ///
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs
index 91a64561824..cecf6dccf9d 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs
@@ -3,6 +3,7 @@
 
 #![feature(supertrait_item_shadowing)]
 #![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
 #![allow(dead_code)]
 
 trait A {
@@ -21,6 +22,7 @@ impl<T> B for T {}
 
 trait C: A + B {
     fn hello(&self) {
+        //~^ WARN trait item `hello` from `C` shadows identically named item
         println!("C");
     }
 }
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr
index a22c5430fef..934d5a0f7cf 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr
@@ -1,16 +1,36 @@
 warning: trait item `hello` from `C` shadows identically named item from supertrait
-  --> $DIR/common-ancestor-2.rs:30:8
+  --> $DIR/common-ancestor-2.rs:24:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+   |
+note: items from several supertraits are shadowed: `B` and `A`
+  --> $DIR/common-ancestor-2.rs:10:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/common-ancestor-2.rs:6:9
+   |
+LL | #![warn(supertrait_item_shadowing_definition)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: trait item `hello` from `C` shadows identically named item from supertrait
+  --> $DIR/common-ancestor-2.rs:32:8
    |
 LL |     ().hello();
    |        ^^^^^
    |
 note: item from `C` shadows a supertrait item
-  --> $DIR/common-ancestor-2.rs:23:5
+  --> $DIR/common-ancestor-2.rs:24:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
 note: items from several supertraits are shadowed: `A` and `B`
-  --> $DIR/common-ancestor-2.rs:9:5
+  --> $DIR/common-ancestor-2.rs:10:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
@@ -23,5 +43,5 @@ note: the lint level is defined here
 LL | #![warn(supertrait_item_shadowing_usage)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 1 warning emitted
+warning: 2 warnings emitted
 
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs
index c2b0ef39bb1..040fa9aab39 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs
@@ -3,6 +3,7 @@
 
 #![feature(supertrait_item_shadowing)]
 #![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
 #![allow(dead_code)]
 
 trait A {
@@ -21,6 +22,7 @@ impl<T> B for T {}
 
 trait C: A + B {
     fn hello(&self) {
+        //~^ WARN trait item `hello` from `C` shadows identically named item
         println!("C");
     }
 }
@@ -30,6 +32,7 @@ impl<T> C for T {}
 
 trait D: C {
     fn hello(&self) {
+        //~^ WARN trait item `hello` from `D` shadows identically named item
         println!("D");
     }
 }
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr
index 072f4fe0208..28e44a2ff20 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr
@@ -1,16 +1,54 @@
+warning: trait item `hello` from `C` shadows identically named item from supertrait
+  --> $DIR/common-ancestor-3.rs:24:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+   |
+note: items from several supertraits are shadowed: `B` and `A`
+  --> $DIR/common-ancestor-3.rs:10:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/common-ancestor-3.rs:6:9
+   |
+LL | #![warn(supertrait_item_shadowing_definition)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: trait item `hello` from `D` shadows identically named item from supertrait
+  --> $DIR/common-ancestor-3.rs:34:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+   |
+note: items from several supertraits are shadowed: `C`, `B`, and `A`
+  --> $DIR/common-ancestor-3.rs:10:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+
 warning: trait item `hello` from `D` shadows identically named item from supertrait
-  --> $DIR/common-ancestor-3.rs:39:8
+  --> $DIR/common-ancestor-3.rs:42:8
    |
 LL |     ().hello();
    |        ^^^^^
    |
 note: item from `D` shadows a supertrait item
-  --> $DIR/common-ancestor-3.rs:32:5
+  --> $DIR/common-ancestor-3.rs:34:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
 note: items from several supertraits are shadowed: `A`, `B`, and `C`
-  --> $DIR/common-ancestor-3.rs:9:5
+  --> $DIR/common-ancestor-3.rs:10:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
@@ -26,5 +64,5 @@ note: the lint level is defined here
 LL | #![warn(supertrait_item_shadowing_usage)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 1 warning emitted
+warning: 3 warnings emitted
 
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor.rs
index 28f415a4772..8e67c935367 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor.rs
@@ -3,6 +3,7 @@
 
 #![feature(supertrait_item_shadowing)]
 #![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
 #![allow(dead_code)]
 
 trait A {
@@ -14,6 +15,7 @@ impl<T> A for T {}
 
 trait B: A {
     fn hello(&self) {
+        //~^ WARN trait item `hello` from `B` shadows identically named item
         println!("B");
     }
 }
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr
index 8ba0529ad9f..f404fa6b53a 100644
--- a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr
@@ -1,16 +1,33 @@
 warning: trait item `hello` from `B` shadows identically named item from supertrait
-  --> $DIR/common-ancestor.rs:23:8
+  --> $DIR/common-ancestor.rs:17:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+   |
+note: item from `A` is shadowed by a subtrait item
+  --> $DIR/common-ancestor.rs:10:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/common-ancestor.rs:6:9
+   |
+LL | #![warn(supertrait_item_shadowing_definition)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: trait item `hello` from `B` shadows identically named item from supertrait
+  --> $DIR/common-ancestor.rs:25:8
    |
 LL |     ().hello();
    |        ^^^^^
    |
 note: item from `B` shadows a supertrait item
-  --> $DIR/common-ancestor.rs:16:5
+  --> $DIR/common-ancestor.rs:17:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
 note: item from `A` is shadowed by a subtrait item
-  --> $DIR/common-ancestor.rs:9:5
+  --> $DIR/common-ancestor.rs:10:5
    |
 LL |     fn hello(&self) {
    |     ^^^^^^^^^^^^^^^
@@ -20,5 +37,5 @@ note: the lint level is defined here
 LL | #![warn(supertrait_item_shadowing_usage)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 1 warning emitted
+warning: 2 warnings emitted
 
diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.rs b/tests/ui/methods/supertrait-shadowing/definition-site.rs
new file mode 100644
index 00000000000..2768a6a6b27
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/definition-site.rs
@@ -0,0 +1,18 @@
+#![feature(supertrait_item_shadowing)]
+#![deny(supertrait_item_shadowing_definition)]
+
+trait SuperSuper {
+    fn method();
+}
+
+trait Super: SuperSuper {
+    fn method();
+    //~^ ERROR trait item `method` from `Super` shadows identically named item
+}
+
+trait Sub: Super {
+    fn method();
+    //~^ ERROR trait item `method` from `Sub` shadows identically named item
+}
+
+fn main() {}
diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.stderr b/tests/ui/methods/supertrait-shadowing/definition-site.stderr
new file mode 100644
index 00000000000..f0bbf414a69
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/definition-site.stderr
@@ -0,0 +1,34 @@
+error: trait item `method` from `Super` shadows identically named item from supertrait
+  --> $DIR/definition-site.rs:9:5
+   |
+LL |     fn method();
+   |     ^^^^^^^^^^^^
+   |
+note: item from `SuperSuper` is shadowed by a subtrait item
+  --> $DIR/definition-site.rs:5:5
+   |
+LL |     fn method();
+   |     ^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/definition-site.rs:2:9
+   |
+LL | #![deny(supertrait_item_shadowing_definition)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait item `method` from `Sub` shadows identically named item from supertrait
+  --> $DIR/definition-site.rs:14:5
+   |
+LL |     fn method();
+   |     ^^^^^^^^^^^^
+   |
+note: items from several supertraits are shadowed: `Super` and `SuperSuper`
+  --> $DIR/definition-site.rs:5:5
+   |
+LL |     fn method();
+   |     ^^^^^^^^^^^^
+...
+LL |     fn method();
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs
index 7cafb0c7ebd..c3bc47e6740 100644
--- a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs
+++ b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs
@@ -1,5 +1,6 @@
 #![feature(supertrait_item_shadowing)]
 #![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
 
 struct W<T>(T);
 
@@ -10,6 +11,7 @@ impl<T> Upstream for T {}
 
 trait Downstream: Upstream {
     fn hello(&self) {}
+    //~^ WARN trait item `hello` from `Downstream` shadows identically named item
 }
 impl<T> Downstream for W<T> where T: Foo {}
 
diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr
index c0555b95f3c..47019ca7a32 100644
--- a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr
+++ b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr
@@ -1,16 +1,33 @@
 warning: trait item `hello` from `Downstream` shadows identically named item from supertrait
-  --> $DIR/false-subtrait-after-inference.rs:20:7
+  --> $DIR/false-subtrait-after-inference.rs:13:5
+   |
+LL |     fn hello(&self) {}
+   |     ^^^^^^^^^^^^^^^
+   |
+note: item from `Upstream` is shadowed by a subtrait item
+  --> $DIR/false-subtrait-after-inference.rs:8:5
+   |
+LL |     fn hello(&self) {}
+   |     ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/false-subtrait-after-inference.rs:3:9
+   |
+LL | #![warn(supertrait_item_shadowing_definition)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: trait item `hello` from `Downstream` shadows identically named item from supertrait
+  --> $DIR/false-subtrait-after-inference.rs:22:7
    |
 LL |     x.hello();
    |       ^^^^^
    |
 note: item from `Downstream` shadows a supertrait item
-  --> $DIR/false-subtrait-after-inference.rs:12:5
+  --> $DIR/false-subtrait-after-inference.rs:13:5
    |
 LL |     fn hello(&self) {}
    |     ^^^^^^^^^^^^^^^
 note: item from `Upstream` is shadowed by a subtrait item
-  --> $DIR/false-subtrait-after-inference.rs:7:5
+  --> $DIR/false-subtrait-after-inference.rs:8:5
    |
 LL |     fn hello(&self) {}
    |     ^^^^^^^^^^^^^^^
@@ -21,22 +38,22 @@ LL | #![warn(supertrait_item_shadowing_usage)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/false-subtrait-after-inference.rs:20:7
+  --> $DIR/false-subtrait-after-inference.rs:22:7
    |
 LL |     x.hello();
    |       ^^^^^ the trait `Foo` is not implemented for `i32`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/false-subtrait-after-inference.rs:16:1
+  --> $DIR/false-subtrait-after-inference.rs:18:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required for `W<i32>` to implement `Downstream`
-  --> $DIR/false-subtrait-after-inference.rs:14:9
+  --> $DIR/false-subtrait-after-inference.rs:16:9
    |
 LL | impl<T> Downstream for W<T> where T: Foo {}
    |         ^^^^^^^^^^     ^^^^          --- unsatisfied trait bound introduced here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0277`.