diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index b3fdafe36e611..7dbc156c5466a 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -633,6 +633,8 @@ declare_features! (
     (unstable, strict_provenance_lints, "1.61.0", Some(130351)),
     /// Allows string patterns to dereference values to match them.
     (unstable, string_deref_patterns, "1.67.0", Some(87121)),
+    /// Allows subtrait items to shadow supertrait items.
+    (unstable, supertrait_item_shadowing, "CURRENT_RUSTC_VERSION", Some(89151)),
     /// Allows using `#[thread_local]` on `static` items.
     (unstable, thread_local, "1.0.0", Some(29594)),
     /// Allows defining `trait X = A + B;` alias items.
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 7344ea01fb214..5560d087e96f0 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 1689437ffb0ed..4218f4ef0c157 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 1574506de603b..14ea10461cbea 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/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 0f424a39840a3..a994b31aeb437 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -192,6 +192,14 @@ hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `
 
 hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead
 
+hir_typeck_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits}
+
+hir_typeck_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item
+
+hir_typeck_supertrait_item_shadower = item from `{$subtrait}` shadows a supertrait item
+
+hir_typeck_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
+
 hir_typeck_trivial_cast = trivial {$numeric ->
     [true] numeric cast
     *[false] cast
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 143736072aa55..1bf8aa4f78d4d 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -868,3 +868,38 @@ pub(crate) struct ReplaceCommaWithSemicolon {
     pub comma_span: Span,
     pub descr: &'static str,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_typeck_supertrait_item_shadowing)]
+pub(crate) struct SupertraitItemShadowing {
+    pub item: Symbol,
+    pub subtrait: Symbol,
+    #[subdiagnostic]
+    pub shadower: SupertraitItemShadower,
+    #[subdiagnostic]
+    pub shadowee: SupertraitItemShadowee,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_typeck_supertrait_item_shadower)]
+pub(crate) struct SupertraitItemShadower {
+    pub subtrait: Symbol,
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum SupertraitItemShadowee {
+    #[note(hir_typeck_supertrait_item_shadowee)]
+    Labeled {
+        #[primary_span]
+        span: Span,
+        supertrait: Symbol,
+    },
+    #[note(hir_typeck_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 36cc9b40d0081..8fb425ff0c94c 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -10,6 +10,7 @@ use rustc_hir_analysis::hir_ty_lowering::{
     FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason,
 };
 use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
+use rustc_lint::builtin::SUPERTRAIT_ITEM_SHADOWING_USAGE;
 use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
@@ -24,6 +25,7 @@ use rustc_trait_selection::traits;
 use tracing::debug;
 
 use super::{MethodCallee, probe};
+use crate::errors::{SupertraitItemShadowee, SupertraitItemShadower, SupertraitItemShadowing};
 use crate::{FnCtxt, callee};
 
 struct ConfirmContext<'a, 'tcx> {
@@ -141,7 +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);
+
+        // 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
@@ -656,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(
@@ -672,6 +677,45 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         }
     }
 
+    fn lint_shadowed_supertrait_items(
+        &self,
+        pick: &probe::Pick<'_>,
+        segment: &hir::PathSegment<'tcx>,
+    ) {
+        if pick.shadowed_candidates.is_empty() {
+            return;
+        }
+
+        let shadower_span = self.tcx.def_span(pick.item.def_id);
+        let subtrait = self.tcx.item_name(pick.item.trait_container(self.tcx).unwrap());
+        let shadower = SupertraitItemShadower { span: shadower_span, subtrait };
+
+        let shadowee = if let [shadowee] = &pick.shadowed_candidates[..] {
+            let shadowee_span = self.tcx.def_span(shadowee.def_id);
+            let supertrait = self.tcx.item_name(shadowee.trait_container(self.tcx).unwrap());
+            SupertraitItemShadowee::Labeled { span: shadowee_span, supertrait }
+        } else {
+            let (traits, spans): (Vec<_>, Vec<_>) = pick
+                .shadowed_candidates
+                .iter()
+                .map(|item| {
+                    (
+                        self.tcx.item_name(item.trait_container(self.tcx).unwrap()),
+                        self.tcx.def_span(item.def_id),
+                    )
+                })
+                .unzip();
+            SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() }
+        };
+
+        self.tcx.emit_node_span_lint(
+            SUPERTRAIT_ITEM_SHADOWING_USAGE,
+            segment.hir_id,
+            segment.ident.span,
+            SupertraitItemShadowing { shadower, shadowee, item: segment.ident.name, subtrait },
+        );
+    }
+
     fn upcast(
         &mut self,
         source_trait_ref: ty::PolyTraitRef<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 9394fcafd7670..b3e48fd5bb592 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -3,6 +3,7 @@ use std::cmp::max;
 use std::ops::Deref;
 
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sso::SsoHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::HirId;
@@ -33,6 +34,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
     CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
 };
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
+use rustc_type_ir::elaborate::supertrait_def_ids;
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
@@ -224,6 +226,9 @@ pub(crate) struct Pick<'tcx> {
     /// to identify this method. Used only for deshadowing errors.
     /// Only applies for inherent impls.
     pub receiver_steps: Option<usize>,
+
+    /// Candidates that were shadowed by supertraits.
+    pub shadowed_candidates: Vec<ty::AssocItem>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -1634,6 +1639,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
 
         if applicable_candidates.len() > 1 {
+            // We collapse to a subtrait pick *after* filtering unstable candidates
+            // to make sure we don't prefer a unstable subtrait method over a stable
+            // supertrait method.
+            if self.tcx.features().supertrait_item_shadowing() {
+                if let Some(pick) =
+                    self.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
+                {
+                    return Some(Ok(pick));
+                }
+            }
+
             let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
             return Some(Err(MethodError::Ambiguity(sources)));
         }
@@ -1672,6 +1688,7 @@ impl<'tcx> Pick<'tcx> {
             self_ty,
             unstable_candidates: _,
             receiver_steps: _,
+            shadowed_candidates: _,
         } = *self;
         self_ty != other.self_ty || def_id != other.item.def_id
     }
@@ -2081,6 +2098,83 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             self_ty,
             unstable_candidates: vec![],
             receiver_steps: None,
+            shadowed_candidates: vec![],
+        })
+    }
+
+    /// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
+    /// multiple conflicting picks if there is one pick whose trait container is a subtrait
+    /// of the trait containers of all of the other picks.
+    ///
+    /// This implements RFC #3624.
+    fn collapse_candidates_to_subtrait_pick(
+        &self,
+        self_ty: Ty<'tcx>,
+        probes: &[(&Candidate<'tcx>, ProbeResult)],
+    ) -> Option<Pick<'tcx>> {
+        let mut child_candidate = probes[0].0;
+        let mut child_trait = child_candidate.item.trait_container(self.tcx)?;
+        let mut supertraits: SsoHashSet<_> = supertrait_def_ids(self.tcx, child_trait).collect();
+
+        let mut remaining_candidates: Vec<_> = probes[1..].iter().map(|&(p, _)| p).collect();
+        while !remaining_candidates.is_empty() {
+            let mut made_progress = false;
+            let mut next_round = vec![];
+
+            for remaining_candidate in remaining_candidates {
+                let remaining_trait = remaining_candidate.item.trait_container(self.tcx)?;
+                if supertraits.contains(&remaining_trait) {
+                    made_progress = true;
+                    continue;
+                }
+
+                // This pick is not a supertrait of the `child_pick`.
+                // Check if it's a subtrait of the `child_pick`, instead.
+                // If it is, then it must have been a subtrait of every
+                // other pick we've eliminated at this point. It will
+                // take over at this point.
+                let remaining_trait_supertraits: SsoHashSet<_> =
+                    supertrait_def_ids(self.tcx, remaining_trait).collect();
+                if remaining_trait_supertraits.contains(&child_trait) {
+                    child_candidate = remaining_candidate;
+                    child_trait = remaining_trait;
+                    supertraits = remaining_trait_supertraits;
+                    made_progress = true;
+                    continue;
+                }
+
+                // `child_pick` is not a supertrait of this pick.
+                // Don't bail here, since we may be comparing two supertraits
+                // of a common subtrait. These two supertraits won't be related
+                // at all, but we will pick them up next round when we find their
+                // child as we continue iterating in this round.
+                next_round.push(remaining_candidate);
+            }
+
+            if made_progress {
+                // If we've made progress, iterate again.
+                remaining_candidates = next_round;
+            } else {
+                // Otherwise, we must have at least two candidates which
+                // are not related to each other at all.
+                return None;
+            }
+        }
+
+        Some(Pick {
+            item: child_candidate.item,
+            kind: TraitPick,
+            import_ids: child_candidate.import_ids.clone(),
+            autoderefs: 0,
+            autoref_or_ptr_adjustment: None,
+            self_ty,
+            unstable_candidates: vec![],
+            shadowed_candidates: probes
+                .iter()
+                .map(|(c, _)| c.item)
+                .filter(|item| item.def_id != child_candidate.item.def_id)
+                .collect(),
+            receiver_steps: None,
         })
     }
 
@@ -2378,6 +2472,7 @@ impl<'tcx> Candidate<'tcx> {
                 InherentImplCandidate { receiver_steps, .. } => Some(receiver_steps),
                 _ => None,
             },
+            shadowed_candidates: vec![],
         }
     }
 }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 9561b3de5f8b6..10bf4ec77ed93 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -101,6 +101,8 @@ 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,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
@@ -4916,6 +4918,87 @@ declare_lint! {
     };
 }
 
+declare_lint! {
+    /// The `supertrait_item_shadowing_usage` lint detects when the
+    /// usage 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_usage)]
+    ///
+    /// trait Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Upstream for T {}
+    ///
+    /// trait Downstream: Upstream {
+    ///     fn hello(&self) {}
+    /// }
+    /// impl<T> Downstream for T {}
+    ///
+    /// struct MyType;
+    /// MyType.hello();
+    /// ```
+    ///
+    /// {{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 the call sites.
+    pub SUPERTRAIT_ITEM_SHADOWING_USAGE,
+    // FIXME(supertrait_item_shadowing): It is not decided if this should
+    // warn by default at the call site.
+    Allow,
+    "detects when a supertrait item is shadowed by a subtrait item",
+    @feature_gate = supertrait_item_shadowing;
+}
+
+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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9734926810ab2..34ecc18a6c602 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1995,6 +1995,7 @@ symbols! {
         sub_assign,
         sub_with_overflow,
         suggestion,
+        supertrait_item_shadowing,
         surface_async_drop_in_place,
         sym,
         sync,
diff --git a/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.rs b/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.rs
new file mode 100644
index 0000000000000..218d2eefeaff7
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.rs
@@ -0,0 +1,22 @@
+trait Sup {
+    fn method(&self) {}
+}
+
+trait Trait: Sup {
+    fn method(&self) {}
+}
+
+impl Sup for i32 {}
+impl Trait for i32 {}
+
+fn poly<T: Trait>(x: T) {
+    x.method();
+    //~^ ERROR multiple applicable items in scope
+}
+
+fn concrete() {
+    1.method();
+    //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.stderr b/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.stderr
new file mode 100644
index 0000000000000..5669073f4abb7
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-supertrait-item-shadowing.stderr
@@ -0,0 +1,57 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:13:7
+   |
+LL |     x.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in the trait `Sup`
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
+   |
+LL |     fn method(&self) {}
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `Trait`
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
+   |
+LL |     fn method(&self) {}
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.method();
+LL +     Sup::method(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.method();
+LL +     Trait::method(&x);
+   |
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:18:7
+   |
+LL |     1.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in an impl of the trait `Sup` for the type `i32`
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
+   |
+LL |     fn method(&self) {}
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait` for the type `i32`
+  --> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
+   |
+LL |     fn method(&self) {}
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     1.method();
+LL +     Sup::method(&1);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     1.method();
+LL +     Trait::method(&1);
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const.rs b/tests/ui/methods/supertrait-shadowing/assoc-const.rs
new file mode 100644
index 0000000000000..a542ce7d326d1
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/assoc-const.rs
@@ -0,0 +1,23 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(supertrait_item_shadowing)]
+#![allow(dead_code)]
+
+trait A {
+    const CONST: i32;
+}
+impl<T> A for T {
+    const CONST: i32 = 1;
+}
+
+trait B: A {
+    const CONST: i32;
+}
+impl<T> B for T {
+    const CONST: i32 = 2;
+}
+
+fn main() {
+    println!("{}", i32::CONST);
+}
diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const.run.stdout b/tests/ui/methods/supertrait-shadowing/assoc-const.run.stdout
new file mode 100644
index 0000000000000..0cfbf08886fca
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/assoc-const.run.stdout
@@ -0,0 +1 @@
+2
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs
new file mode 100644
index 0000000000000..cecf6dccf9d16
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs
@@ -0,0 +1,34 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(supertrait_item_shadowing)]
+#![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
+#![allow(dead_code)]
+
+trait A {
+    fn hello(&self) {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B {
+    fn hello(&self) {
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+trait C: A + B {
+    fn hello(&self) {
+        //~^ WARN trait item `hello` from `C` shadows identically named item
+        println!("C");
+    }
+}
+impl<T> C for T {}
+
+fn main() {
+    ().hello();
+    //~^ WARN trait item `hello` from `C` shadows identically named item from supertrait
+}
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.run.stdout b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.run.stdout
new file mode 100644
index 0000000000000..3cc58df837521
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.run.stdout
@@ -0,0 +1 @@
+C
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr
new file mode 100644
index 0000000000000..934d5a0f7cfd3
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr
@@ -0,0 +1,47 @@
+warning: trait item `hello` from `C` shadows identically named item from supertrait
+  --> $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:24:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: items from several supertraits are shadowed: `A` and `B`
+  --> $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:5:9
+   |
+LL | #![warn(supertrait_item_shadowing_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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
new file mode 100644
index 0000000000000..040fa9aab3987
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs
@@ -0,0 +1,44 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(supertrait_item_shadowing)]
+#![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
+#![allow(dead_code)]
+
+trait A {
+    fn hello(&self) {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B {
+    fn hello(&self) {
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+trait C: A + B {
+    fn hello(&self) {
+        //~^ WARN trait item `hello` from `C` shadows identically named item
+        println!("C");
+    }
+}
+impl<T> C for T {}
+
+// `D` extends `C` which extends `B` and `A`
+
+trait D: C {
+    fn hello(&self) {
+        //~^ WARN trait item `hello` from `D` shadows identically named item
+        println!("D");
+    }
+}
+impl<T> D for T {}
+
+fn main() {
+    ().hello();
+    //~^ WARN trait item `hello` from `D` shadows identically named item from supertrait
+}
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.run.stdout b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.run.stdout
new file mode 100644
index 0000000000000..178481050188c
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.run.stdout
@@ -0,0 +1 @@
+D
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr
new file mode 100644
index 0000000000000..28e44a2ff209a
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr
@@ -0,0 +1,68 @@
+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:42:8
+   |
+LL |     ().hello();
+   |        ^^^^^
+   |
+note: item from `D` shadows a supertrait item
+  --> $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:10:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+...
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/common-ancestor-3.rs:5:9
+   |
+LL | #![warn(supertrait_item_shadowing_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs b/tests/ui/methods/supertrait-shadowing/common-ancestor.rs
new file mode 100644
index 0000000000000..8e67c93536755
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor.rs
@@ -0,0 +1,27 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(supertrait_item_shadowing)]
+#![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
+#![allow(dead_code)]
+
+trait A {
+    fn hello(&self) {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B: A {
+    fn hello(&self) {
+        //~^ WARN trait item `hello` from `B` shadows identically named item
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+fn main() {
+    ().hello();
+    //~^ WARN trait item `hello` from `B` shadows identically named item from supertrait
+}
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.run.stdout b/tests/ui/methods/supertrait-shadowing/common-ancestor.run.stdout
new file mode 100644
index 0000000000000..223b7836fb19f
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor.run.stdout
@@ -0,0 +1 @@
+B
diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr b/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr
new file mode 100644
index 0000000000000..f404fa6b53a35
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr
@@ -0,0 +1,41 @@
+warning: trait item `hello` from `B` shadows identically named item from supertrait
+  --> $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: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:5:9
+   |
+LL | #![warn(supertrait_item_shadowing_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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 0000000000000..2768a6a6b2717
--- /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 0000000000000..f0bbf414a690c
--- /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
new file mode 100644
index 0000000000000..c3bc47e6740d8
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs
@@ -0,0 +1,26 @@
+#![feature(supertrait_item_shadowing)]
+#![warn(supertrait_item_shadowing_usage)]
+#![warn(supertrait_item_shadowing_definition)]
+
+struct W<T>(T);
+
+trait Upstream {
+    fn hello(&self) {}
+}
+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 {}
+
+trait Foo {}
+
+fn main() {
+    let x = W(Default::default());
+    x.hello();
+    //~^ ERROR the trait bound `i32: Foo` is not satisfied
+    //~| WARN trait item `hello` from `Downstream` shadows identically named item from supertrait
+    let _: i32 = x.0;
+}
diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr
new file mode 100644
index 0000000000000..47019ca7a320f
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr
@@ -0,0 +1,59 @@
+warning: trait item `hello` from `Downstream` shadows identically named item from supertrait
+  --> $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: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:2:9
+   |
+LL | #![warn(supertrait_item_shadowing_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $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:18:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
+note: required for `W<i32>` to implement `Downstream`
+  --> $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; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs
new file mode 100644
index 0000000000000..2834ca31b7140
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs
@@ -0,0 +1,37 @@
+#![feature(supertrait_item_shadowing)]
+
+trait A {
+    fn hello(&self) {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B {
+    fn hello(&self) {
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+trait C: A + B {
+    fn hello(&self) {
+        println!("C");
+    }
+}
+impl<T> C for T {}
+
+// Since `D` is not a subtrait of `C`,
+// we have no obvious lower bound.
+
+trait D: B {
+    fn hello(&self) {
+        println!("D");
+    }
+}
+impl<T> D for T {}
+
+fn main() {
+    ().hello();
+    //~^ ERROR multiple applicable items in scope
+}
diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr
new file mode 100644
index 0000000000000..231cb9b1cb2bc
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr
@@ -0,0 +1,50 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/no-common-ancestor-2.rs:35:8
+   |
+LL |     ().hello();
+   |        ^^^^^ multiple `hello` found
+   |
+note: candidate #1 is defined in an impl of the trait `A` for the type `T`
+  --> $DIR/no-common-ancestor-2.rs:4:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `B` for the type `T`
+  --> $DIR/no-common-ancestor-2.rs:11:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: candidate #3 is defined in an impl of the trait `C` for the type `T`
+  --> $DIR/no-common-ancestor-2.rs:18:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: candidate #4 is defined in an impl of the trait `D` for the type `T`
+  --> $DIR/no-common-ancestor-2.rs:28:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     ().hello();
+LL +     A::hello(&());
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     ().hello();
+LL +     B::hello(&());
+   |
+help: disambiguate the method for candidate #3
+   |
+LL -     ().hello();
+LL +     C::hello(&());
+   |
+help: disambiguate the method for candidate #4
+   |
+LL -     ().hello();
+LL +     D::hello(&());
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs
new file mode 100644
index 0000000000000..7323439d5884f
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs
@@ -0,0 +1,20 @@
+#![feature(supertrait_item_shadowing)]
+
+trait A {
+    fn hello(&self) {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B {
+    fn hello(&self) {
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+fn main() {
+    ().hello();
+    //~^ ERROR multiple applicable items in scope
+}
diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr
new file mode 100644
index 0000000000000..4e83f60c76514
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/no-common-ancestor.rs:18:8
+   |
+LL |     ().hello();
+   |        ^^^^^ multiple `hello` found
+   |
+note: candidate #1 is defined in an impl of the trait `A` for the type `T`
+  --> $DIR/no-common-ancestor.rs:4:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `B` for the type `T`
+  --> $DIR/no-common-ancestor.rs:11:5
+   |
+LL |     fn hello(&self) {
+   |     ^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     ().hello();
+LL +     A::hello(&());
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     ().hello();
+LL +     B::hello(&());
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/supertrait-shadowing/out-of-scope.rs b/tests/ui/methods/supertrait-shadowing/out-of-scope.rs
new file mode 100644
index 0000000000000..bd263be59cc7d
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/out-of-scope.rs
@@ -0,0 +1,25 @@
+//@ run-pass
+//@ check-run-results
+
+#![feature(supertrait_item_shadowing)]
+#![allow(dead_code)]
+
+mod out_of_scope {
+    pub trait Subtrait: super::Supertrait {
+        fn hello(&self) {
+            println!("subtrait");
+        }
+    }
+    impl<T> Subtrait for T {}
+}
+
+trait Supertrait {
+    fn hello(&self) {
+        println!("supertrait");
+    }
+}
+impl<T> Supertrait for T {}
+
+fn main() {
+    ().hello();
+}
diff --git a/tests/ui/methods/supertrait-shadowing/out-of-scope.run.stdout b/tests/ui/methods/supertrait-shadowing/out-of-scope.run.stdout
new file mode 100644
index 0000000000000..1019e5f354346
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/out-of-scope.run.stdout
@@ -0,0 +1 @@
+supertrait
diff --git a/tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs b/tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs
new file mode 100644
index 0000000000000..e44c7c18083d0
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+// Make sure we don't prefer a subtrait that we would've otherwise eliminated
+// in `consider_probe` during method probing.
+
+#![feature(supertrait_item_shadowing)]
+#![allow(dead_code)]
+
+struct W<T>(T);
+
+trait Upstream {
+    fn hello(&self) {}
+}
+impl<T> Upstream for T {}
+
+trait Downstream: Upstream {
+    fn hello(&self) {}
+}
+impl<T> Downstream for W<T> where T: Foo {}
+
+trait Foo {}
+
+fn main() {
+    let x = W(1i32);
+    x.hello();
+}
diff --git a/tests/ui/methods/supertrait-shadowing/type-dependent.rs b/tests/ui/methods/supertrait-shadowing/type-dependent.rs
new file mode 100644
index 0000000000000..3af884fd52dcd
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/type-dependent.rs
@@ -0,0 +1,29 @@
+//@ run-pass
+//@ check-run-results
+
+// Makes sure we can shadow with type-dependent method syntax.
+
+#![feature(supertrait_item_shadowing)]
+#![allow(dead_code)]
+
+trait A {
+    fn hello() {
+        println!("A");
+    }
+}
+impl<T> A for T {}
+
+trait B: A {
+    fn hello() {
+        println!("B");
+    }
+}
+impl<T> B for T {}
+
+fn foo<T>() {
+    T::hello();
+}
+
+fn main() {
+    foo::<()>();
+}
diff --git a/tests/ui/methods/supertrait-shadowing/type-dependent.run.stdout b/tests/ui/methods/supertrait-shadowing/type-dependent.run.stdout
new file mode 100644
index 0000000000000..223b7836fb19f
--- /dev/null
+++ b/tests/ui/methods/supertrait-shadowing/type-dependent.run.stdout
@@ -0,0 +1 @@
+B