about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-11-23 06:22:30 +0000
committerbors <bors@rust-lang.org>2023-11-23 06:22:30 +0000
commitfc13ca6d70f7381513c22443fc5aaee1d151ea45 (patch)
tree5b5850aed44cce940bcee12fe42ce1f9a809ecea
parent193466525d3433562718ee5cecb5ff11ef6d6e3f (diff)
parent0223a811f57f4cc05096985bad6632911fdcc532 (diff)
downloadrust-fc13ca6d70f7381513c22443fc5aaee1d151ea45.tar.gz
rust-fc13ca6d70f7381513c22443fc5aaee1d151ea45.zip
Auto merge of #118200 - matthiaskrgr:rollup-neka6xo, r=matthiaskrgr
Rollup of 4 pull requests

Successful merges:

 - #118131 (improve tool-only help for multiple `#[default]` variants)
 - #118146 (Rework supertrait lint once again)
 - #118167 (make the 'abi_unadjusted' feature internal)
 - #118169 (print query map for deadlock when using parallel front end)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs17
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs42
-rw-r--r--compiler/rustc_lint/src/lints.rs14
-rw-r--r--compiler/rustc_query_system/src/query/job.rs16
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs2
-rw-r--r--tests/ui/deriving/issue-105101.rs9
-rw-r--r--tests/ui/deriving/issue-105101.stderr29
-rw-r--r--tests/ui/deriving/multiple-defaults.rs41
-rw-r--r--tests/ui/deriving/multiple-defaults.stderr62
-rw-r--r--tests/ui/traits/trait-upcasting/deref-lint-regions.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/deref-lint.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/deref-lint.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs34
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr16
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs20
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr14
18 files changed, 249 insertions, 79 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 07b172bc757..43874a242f2 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -127,18 +127,17 @@ fn extract_default_variant<'a>(
         [first, rest @ ..] => {
             let suggs = default_variants
                 .iter()
-                .map(|variant| {
-                    let spans = default_variants
+                .filter_map(|variant| {
+                    let keep = attr::find_by_name(&variant.attrs, kw::Default)?.span;
+                    let spans: Vec<Span> = default_variants
                         .iter()
-                        .filter_map(|v| {
-                            if v.span == variant.span {
-                                None
-                            } else {
-                                Some(attr::find_by_name(&v.attrs, kw::Default)?.span)
-                            }
+                        .flat_map(|v| {
+                            attr::filter_by_name(&v.attrs, kw::Default)
+                                .filter_map(|attr| (attr.span != keep).then_some(attr.span))
                         })
                         .collect();
-                    errors::MultipleDefaultsSugg { spans, ident: variant.ident }
+                    (!spans.is_empty())
+                        .then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
                 })
                 .collect();
             cx.emit_err(errors::MultipleDefaults {
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d1b3fec8a0b..35726ba52bc 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -160,7 +160,7 @@ declare_features! (
     // no-tracking-issue-start
 
     /// Allows using the `unadjusted` ABI; perma-unstable.
-    (unstable, abi_unadjusted, "1.16.0", None, None),
+    (internal, abi_unadjusted, "1.16.0", None, None),
     /// Allows using the `vectorcall` ABI.
     (unstable, abi_vectorcall, "1.7.0", None, None),
     /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 80b21bd8ece..2db610d640c 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -491,8 +491,9 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
 lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
 
 lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
+    .label = `{$self_ty}` implements `Deref<Target = dyn {$target_principal}>` which conflicts with supertrait `{$supertrait_principal}`
+    .label2 = target type is a supertrait of `{$self_ty}`
     .help = consider removing this implementation or replacing it with a method instead
-    .label = target type is a supertrait of `{$t}`
 
 lint_suspicious_double_ref_clone =
     using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 93c7c37c655..98bafc0f263 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -53,35 +53,43 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
         let tcx = cx.tcx;
         // `Deref` is being implemented for `t`
         if let hir::ItemKind::Impl(impl_) = item.kind
+            // the trait is a `Deref` implementation
             && let Some(trait_) = &impl_.of_trait
-            && let t = tcx.type_of(item.owner_id).instantiate_identity()
-            && let opt_did @ Some(did) = trait_.trait_def_id()
-            && opt_did == tcx.lang_items().deref_trait()
-            // `t` is `dyn t_principal`
-            && let ty::Dynamic(data, _, ty::Dyn) = t.kind()
-            && let Some(t_principal) = data.principal()
+            && let Some(did) = trait_.trait_def_id()
+            && Some(did) == tcx.lang_items().deref_trait()
+            // the self type is `dyn t_principal`
+            && let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
+            && let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
+            && let Some(self_principal) = data.principal()
             // `<T as Deref>::Target` is `dyn target_principal`
-            && let Some(target) = cx.get_associated_type(t, did, "Target")
+            && let Some(target) = cx.get_associated_type(self_ty, did, "Target")
             && let ty::Dynamic(data, _, ty::Dyn) = target.kind()
             && let Some(target_principal) = data.principal()
             // `target_principal` is a supertrait of `t_principal`
-            && supertraits(tcx, t_principal.with_self_ty(tcx, tcx.types.trait_object_dummy_self))
-                .any(|sup| {
-                    tcx.erase_regions(
-                        sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(tcx, x)),
-                    ) == tcx.erase_regions(target_principal)
-                })
+            && let Some(supertrait_principal) = supertraits(tcx, self_principal.with_self_ty(tcx, self_ty))
+                .find(|supertrait| supertrait.def_id() == target_principal.def_id())
         {
-            let t = tcx.erase_regions(t);
-            let label = impl_
+            // erase regions in self type for better diagnostic presentation
+            let (self_ty, target_principal, supertrait_principal) =
+                tcx.erase_regions((self_ty, target_principal, supertrait_principal));
+            let label2 = impl_
                 .items
                 .iter()
                 .find_map(|i| (i.ident.name == sym::Target).then_some(i.span))
                 .map(|label| SupertraitAsDerefTargetLabel { label });
+            let span = tcx.def_span(item.owner_id.def_id);
             cx.emit_spanned_lint(
                 DEREF_INTO_DYN_SUPERTRAIT,
-                tcx.def_span(item.owner_id.def_id),
-                SupertraitAsDerefTarget { t, label },
+                span,
+                SupertraitAsDerefTarget {
+                    self_ty,
+                    supertrait_principal: supertrait_principal.map_bound(|trait_ref| {
+                        ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
+                    }),
+                    target_principal,
+                    label: span,
+                    label2,
+                },
             );
         }
     }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 7fe488e1243..9fda53c2533 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -10,7 +10,9 @@ use rustc_errors::{
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{inhabitedness::InhabitedPredicate, Clause, Ty, TyCtxt};
+use rustc_middle::ty::{
+    inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
+};
 use rustc_session::parse::ParseSess;
 use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
 
@@ -556,13 +558,17 @@ pub enum BuiltinSpecialModuleNameUsed {
 #[diag(lint_supertrait_as_deref_target)]
 #[help]
 pub struct SupertraitAsDerefTarget<'a> {
-    pub t: Ty<'a>,
+    pub self_ty: Ty<'a>,
+    pub supertrait_principal: PolyExistentialTraitRef<'a>,
+    pub target_principal: PolyExistentialTraitRef<'a>,
+    #[label]
+    pub label: Span,
     #[subdiagnostic]
-    pub label: Option<SupertraitAsDerefTargetLabel>,
+    pub label2: Option<SupertraitAsDerefTargetLabel>,
 }
 
 #[derive(Subdiagnostic)]
-#[label(lint_label)]
+#[label(lint_label2)]
 pub struct SupertraitAsDerefTargetLabel {
     #[primary_span]
     pub label: Span,
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index f2c1f84fccc..b38d71733b5 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -38,7 +38,7 @@ pub struct QueryInfo {
 pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
 
 /// A value uniquely identifying an active query job.
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
 pub struct QueryJobId(pub NonZeroU64);
 
 impl QueryJobId {
@@ -62,14 +62,14 @@ impl QueryJobId {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct QueryJobInfo {
     pub query: QueryStackFrame,
     pub job: QueryJob,
 }
 
 /// Represents an active query job.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct QueryJob {
     pub id: QueryJobId,
 
@@ -182,6 +182,7 @@ impl QueryJobId {
 }
 
 #[cfg(parallel_compiler)]
+#[derive(Debug)]
 struct QueryWaiter {
     query: Option<QueryJobId>,
     condvar: Condvar,
@@ -198,13 +199,14 @@ impl QueryWaiter {
 }
 
 #[cfg(parallel_compiler)]
+#[derive(Debug)]
 struct QueryLatchInfo {
     complete: bool,
     waiters: Vec<Arc<QueryWaiter>>,
 }
 
 #[cfg(parallel_compiler)]
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub(super) struct QueryLatch {
     info: Arc<Mutex<QueryLatchInfo>>,
 }
@@ -540,7 +542,11 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
     // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here
     // only considers the true dependency and won't detect a cycle.
     if !found_cycle {
-        panic!("deadlock detected");
+        if query_map.len() == 0 {
+            panic!("deadlock detected without any query!")
+        } else {
+            panic!("deadlock detected! current query map:\n{:#?}", query_map);
+        }
     }
 
     // FIXME: Ensure this won't cause a deadlock before we return
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 6c08df99e9d..ecbc7dc6b8f 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -203,7 +203,7 @@ where
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub(crate) struct CycleError {
     /// The query and related span that uses the cycle.
     pub usage: Option<(Span, QueryStackFrame)>,
diff --git a/tests/ui/deriving/issue-105101.rs b/tests/ui/deriving/issue-105101.rs
deleted file mode 100644
index 1a377feb919..00000000000
--- a/tests/ui/deriving/issue-105101.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --crate-type=lib
-
-#[derive(Default)] //~ ERROR multiple declared defaults
-enum E {
-    #[default]
-    A,
-    #[default]
-    A, //~ ERROR defined multiple times
-}
diff --git a/tests/ui/deriving/issue-105101.stderr b/tests/ui/deriving/issue-105101.stderr
deleted file mode 100644
index 0f6f67043f3..00000000000
--- a/tests/ui/deriving/issue-105101.stderr
+++ /dev/null
@@ -1,29 +0,0 @@
-error: multiple declared defaults
-  --> $DIR/issue-105101.rs:3:10
-   |
-LL | #[derive(Default)]
-   |          ^^^^^^^
-...
-LL |     A,
-   |     - first default
-LL |     #[default]
-LL |     A,
-   |     - additional default
-   |
-   = note: only one variant can be default
-   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0428]: the name `A` is defined multiple times
-  --> $DIR/issue-105101.rs:8:5
-   |
-LL |     A,
-   |     - previous definition of the type `A` here
-LL |     #[default]
-LL |     A,
-   |     ^ `A` redefined here
-   |
-   = note: `A` must be defined only once in the type namespace of this enum
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui/deriving/multiple-defaults.rs b/tests/ui/deriving/multiple-defaults.rs
new file mode 100644
index 00000000000..2024a55200b
--- /dev/null
+++ b/tests/ui/deriving/multiple-defaults.rs
@@ -0,0 +1,41 @@
+// compile-flags: --crate-type=lib
+
+// When we get multiple `#[default]` variants, we emit several tool-only suggestions
+// to remove all except one of the `#[default]`s.
+
+#[derive(Default)] //~ ERROR multiple declared defaults
+enum A {
+    #[default] //~ HELP make `B` default
+    #[default] //~ HELP make `A` default
+    A,
+    #[default] // also "HELP make `A` default", but compiletest can't handle multispans
+    B,
+}
+
+// Originally, we took each defaulted variant and emitted the suggestion for every variant
+// with a different identifier, causing an ICE when multiple variants have the same identifier:
+// https://github.com/rust-lang/rust/pull/105106
+#[derive(Default)] //~ ERROR multiple declared defaults
+enum E {
+    #[default] //~ HELP make `A` default
+    A,
+    #[default] //~ HELP make `A` default
+    A, //~ ERROR defined multiple times
+}
+
+// Then, we took each defaulted variant and emitted the suggestion for every variant
+// with a different span, causing an ICE when multiple variants have the same span:
+// https://github.com/rust-lang/rust/issues/118119
+macro_rules! m {
+    { $($id:ident)* } => {
+        #[derive(Default)] //~ ERROR multiple declared defaults
+        enum F {
+            $(
+                #[default]
+                $id,
+            )*
+        }
+    }
+}
+
+m! { A B }
diff --git a/tests/ui/deriving/multiple-defaults.stderr b/tests/ui/deriving/multiple-defaults.stderr
new file mode 100644
index 00000000000..05fb6fecffa
--- /dev/null
+++ b/tests/ui/deriving/multiple-defaults.stderr
@@ -0,0 +1,62 @@
+error: multiple declared defaults
+  --> $DIR/multiple-defaults.rs:6:10
+   |
+LL | #[derive(Default)]
+   |          ^^^^^^^
+...
+LL |     A,
+   |     - first default
+LL |     #[default] // also "HELP make `A` default", but compiletest can't handle multispans
+LL |     B,
+   |     - additional default
+   |
+   = note: only one variant can be default
+   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: multiple declared defaults
+  --> $DIR/multiple-defaults.rs:18:10
+   |
+LL | #[derive(Default)]
+   |          ^^^^^^^
+...
+LL |     A,
+   |     - first default
+LL |     #[default]
+LL |     A,
+   |     - additional default
+   |
+   = note: only one variant can be default
+   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0428]: the name `A` is defined multiple times
+  --> $DIR/multiple-defaults.rs:23:5
+   |
+LL |     A,
+   |     - previous definition of the type `A` here
+LL |     #[default]
+LL |     A,
+   |     ^ `A` redefined here
+   |
+   = note: `A` must be defined only once in the type namespace of this enum
+
+error: multiple declared defaults
+  --> $DIR/multiple-defaults.rs:31:18
+   |
+LL |         #[derive(Default)]
+   |                  ^^^^^^^
+...
+LL |                 $id,
+   |                 ---
+   |                 |
+   |                 first default
+   |                 additional default
+...
+LL | m! { A B }
+   | ---------- in this macro invocation
+   |
+   = note: only one variant can be default
+   = note: this error originates in the derive macro `Default` which comes from the expansion of the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr b/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr
index dd4aa8e9a07..557a4420a3d 100644
--- a/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr
+++ b/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr
@@ -2,7 +2,7 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
   --> $DIR/deref-lint-regions.rs:8:1
    |
 LL | impl<'a> Deref for dyn Foo<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
 LL |
 LL |     type Target = dyn Bar<'a>;
    |     -------------------------- target type is a supertrait of `dyn Foo<'_>`
diff --git a/tests/ui/traits/trait-upcasting/deref-lint.rs b/tests/ui/traits/trait-upcasting/deref-lint.rs
index dfca7b0fa68..68838d2ae20 100644
--- a/tests/ui/traits/trait-upcasting/deref-lint.rs
+++ b/tests/ui/traits/trait-upcasting/deref-lint.rs
@@ -8,6 +8,7 @@ trait B: A {}
 
 impl<'a> Deref for dyn 'a + B {
     //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
+
     type Target = dyn A;
     fn deref(&self) -> &Self::Target {
         todo!()
diff --git a/tests/ui/traits/trait-upcasting/deref-lint.stderr b/tests/ui/traits/trait-upcasting/deref-lint.stderr
index 0f7a61dfa80..5a13659edf5 100644
--- a/tests/ui/traits/trait-upcasting/deref-lint.stderr
+++ b/tests/ui/traits/trait-upcasting/deref-lint.stderr
@@ -2,8 +2,8 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
   --> $DIR/deref-lint.rs:9:1
    |
 LL | impl<'a> Deref for dyn 'a + B {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
+...
 LL |     type Target = dyn A;
    |     -------------------- target type is a supertrait of `dyn B`
    |
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
new file mode 100644
index 00000000000..366eae1a58a
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
@@ -0,0 +1,34 @@
+#![deny(deref_into_dyn_supertrait)]
+use std::ops::Deref;
+
+trait Bar<T> {}
+impl<T, U> Bar<U> for T {}
+
+trait Foo: Bar<i32> {
+    fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
+}
+
+impl Foo for () {
+    fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a) {
+        self
+    }
+}
+
+impl<'a> Deref for dyn Foo + 'a {
+    type Target = dyn Bar<u32> + 'a;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_dyn_bar_u32()
+    }
+}
+
+fn take_dyn<T>(x: &dyn Bar<T>) -> T {
+    todo!()
+}
+
+fn main() {
+    let x: &dyn Foo = &();
+    let y = take_dyn(x);
+    let z: u32 = y;
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
new file mode 100644
index 00000000000..e8bab322a38
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/deref-upcast-behavioral-change.rs:32:18
+   |
+LL |     let z: u32 = y;
+   |            ---   ^ expected `u32`, found `i32`
+   |            |
+   |            expected due to this
+   |
+help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+   |
+LL |     let z: u32 = y.try_into().unwrap();
+   |                   ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
new file mode 100644
index 00000000000..2c9126c863d
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+use std::ops::Deref;
+
+trait Bar<T> {}
+
+trait Foo: Bar<i32> {
+    fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
+}
+
+impl<'a> Deref for dyn Foo + 'a {
+    //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
+    type Target = dyn Bar<u32> + 'a;
+
+    fn deref(&self) -> &Self::Target {
+        self.as_dyn_bar_u32()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
new file mode 100644
index 00000000000..a447f9cf83b
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
@@ -0,0 +1,14 @@
+warning: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/migrate-lint-different-substs.rs:11:1
+   |
+LL | impl<'a> Deref for dyn Foo + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
+LL |
+LL |     type Target = dyn Bar<u32> + 'a;
+   |     -------------------------------- target type is a supertrait of `dyn Foo`
+   |
+   = help: consider removing this implementation or replacing it with a method instead
+   = note: `#[warn(deref_into_dyn_supertrait)]` on by default
+
+warning: 1 warning emitted
+