about summary refs log tree commit diff
path: root/tests/ui/dyn-compatibility
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2024-10-09 23:31:01 +0200
committerLeón Orell Valerian Liehr <me@fmease.dev>2024-10-10 01:13:29 +0200
commit20cebae31203a9781f99081b075abe0dc2504a98 (patch)
tree8cde6f126d8cbfdce885dbf10cc56318dd6afeaa /tests/ui/dyn-compatibility
parent2e7a52b22fe222316a48093547f6312252c20f0f (diff)
downloadrust-20cebae31203a9781f99081b075abe0dc2504a98.tar.gz
rust-20cebae31203a9781f99081b075abe0dc2504a98.zip
UI tests: Rename "object safe" to "dyn compatible"
Diffstat (limited to 'tests/ui/dyn-compatibility')
-rw-r--r--tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs60
-rw-r--r--tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr55
-rw-r--r--tests/ui/dyn-compatibility/assoc_const_bounds.rs18
-rw-r--r--tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs14
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds.rs13
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds.stderr21
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds2.rs13
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds2.stderr21
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed11
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs11
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr20
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs24
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs25
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr21
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs15
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr11
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs18
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr44
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.curr.stderr34
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr19
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.rs19
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr41
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr69
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs14
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr47
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr128
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs20
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr20
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr34
-rw-r--r--tests/ui/dyn-compatibility/avoid-ice-on-warning.rs9
-rw-r--r--tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed14
-rw-r--r--tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr21
-rw-r--r--tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr39
-rw-r--r--tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs14
-rw-r--r--tests/ui/dyn-compatibility/bounds.rs12
-rw-r--r--tests/ui/dyn-compatibility/bounds.stderr17
-rw-r--r--tests/ui/dyn-compatibility/by-value-self-use.rs18
-rw-r--r--tests/ui/dyn-compatibility/by-value-self-use.stderr9
-rw-r--r--tests/ui/dyn-compatibility/by-value-self.rs46
-rw-r--r--tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs26
-rw-r--r--tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs26
-rw-r--r--tests/ui/dyn-compatibility/erroneous_signature.rs17
-rw-r--r--tests/ui/dyn-compatibility/erroneous_signature.stderr15
-rw-r--r--tests/ui/dyn-compatibility/generics.curr.stderr80
-rw-r--r--tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr35
-rw-r--r--tests/ui/dyn-compatibility/generics.rs42
-rw-r--r--tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs8
-rw-r--r--tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs11
-rw-r--r--tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs22
-rw-r--r--tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr38
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs44
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr48
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.curr.stderr65
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr35
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.rs42
-rw-r--r--tests/ui/dyn-compatibility/missing-assoc-type.rs10
-rw-r--r--tests/ui/dyn-compatibility/missing-assoc-type.stderr65
-rw-r--r--tests/ui/dyn-compatibility/no-static.curr.stderr73
-rw-r--r--tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr27
-rw-r--r--tests/ui/dyn-compatibility/no-static.rs25
-rw-r--r--tests/ui/dyn-compatibility/phantom-fn.rs22
-rw-r--r--tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs142
-rw-r--r--tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr673
-rw-r--r--tests/ui/dyn-compatibility/sized-2.curr.stderr32
-rw-r--r--tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr18
-rw-r--r--tests/ui/dyn-compatibility/sized-2.rs21
-rw-r--r--tests/ui/dyn-compatibility/sized.curr.stderr32
-rw-r--r--tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr18
-rw-r--r--tests/ui/dyn-compatibility/sized.rs18
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs15
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr42
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-Self.rs22
-rw-r--r--tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr42
-rw-r--r--tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs29
-rw-r--r--tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr54
75 files changed, 2993 insertions, 0 deletions
diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs
new file mode 100644
index 00000000000..83076f7d5fc
--- /dev/null
+++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs
@@ -0,0 +1,60 @@
+// Test for fixed unsoundness in #126079.
+// Enforces that the associated types that are dyn-compatible.
+
+use std::marker::PhantomData;
+
+fn transmute<T, U>(t: T) -> U {
+    (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
+    //~^ ERROR the trait `Foo` cannot be made into an object
+    //~| ERROR the trait `Foo` cannot be made into an object
+}
+
+struct ActuallySuper;
+struct NotActuallySuper;
+trait Super<Q> {
+    type Assoc;
+}
+
+trait Dyn {
+    type Out;
+}
+impl<T, U> Dyn for dyn Foo<T, U> + '_ {
+//~^ ERROR the trait `Foo` cannot be made into an object
+    type Out = U;
+}
+impl<S: Dyn<Out = U> + ?Sized, U> Super<NotActuallySuper> for S {
+    type Assoc = U;
+}
+
+trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
+where
+    <Self as Mirror>::Assoc: Super<NotActuallySuper>
+{
+    fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
+}
+
+trait Mirror {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+    type Assoc = T;
+}
+
+impl<T, U> Foo<T, U> for PhantomData<T> {
+    fn transmute(&self, t: T) -> T {
+        t
+    }
+}
+impl<T> Super<ActuallySuper> for PhantomData<T> {
+    type Assoc = T;
+}
+impl<T> Super<NotActuallySuper> for PhantomData<T> {
+    type Assoc = T;
+}
+
+fn main() {
+    let x = String::from("hello, world");
+    let s = transmute::<&str, &'static str>(x.as_str());
+    drop(x);
+    println!("> {s}");
+}
diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
new file mode 100644
index 00000000000..99bcccc20c0
--- /dev/null
+++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
@@ -0,0 +1,55 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/almost-supertrait-associated-type.rs:21:20
+   |
+LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {
+   |                    ^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/almost-supertrait-associated-type.rs:33:34
+   |
+LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
+   = help: consider moving `transmute` to another trait
+   = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/almost-supertrait-associated-type.rs:7:27
+   |
+LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
+   |                           ^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/almost-supertrait-associated-type.rs:33:34
+   |
+LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
+   = help: consider moving `transmute` to another trait
+   = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/almost-supertrait-associated-type.rs:7:6
+   |
+LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
+   |      ^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/almost-supertrait-associated-type.rs:33:34
+   |
+LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
+   |       --- this trait cannot be made into an object...
+...
+LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
+   = help: consider moving `transmute` to another trait
+   = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead
+   = note: required for the cast from `&PhantomData<T>` to `&dyn Foo<T, U>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/assoc_const_bounds.rs b/tests/ui/dyn-compatibility/assoc_const_bounds.rs
new file mode 100644
index 00000000000..32c4de1981b
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_const_bounds.rs
@@ -0,0 +1,18 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features, dead_code)]
+
+//@ check-pass
+
+trait Foo<T> {
+    const BAR: bool
+    where
+        Self: Sized;
+}
+
+trait Cake {}
+impl Cake for () {}
+
+fn foo(_: &dyn Foo<()>) {}
+fn bar(_: &dyn Foo<i32>) {}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs
new file mode 100644
index 00000000000..1272a735e83
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs
@@ -0,0 +1,14 @@
+#![feature(generic_const_items)]
+#![allow(incomplete_features, dead_code)]
+
+//@ check-pass
+
+trait Foo {
+    const BAR: bool
+    where
+        Self: Sized;
+}
+
+fn foo(_: &dyn Foo) {}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs
new file mode 100644
index 00000000000..8634ba626a1
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds.rs
@@ -0,0 +1,13 @@
+trait Foo<T> {
+    type Bar
+    where
+        T: Cake;
+}
+
+trait Cake {}
+impl Cake for () {}
+
+fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr
new file mode 100644
index 00000000000..3d5482625af
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr
@@ -0,0 +1,21 @@
+error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+  --> $DIR/assoc_type_bounds.rs:10:16
+   |
+LL |     type Bar
+   |     -------- `Bar` defined here
+...
+LL | fn foo(_: &dyn Foo<()>) {}
+   |                ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
+
+error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+  --> $DIR/assoc_type_bounds.rs:11:16
+   |
+LL |     type Bar
+   |     -------- `Bar` defined here
+...
+LL | fn bar(_: &dyn Foo<i32>) {}
+   |                ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = Type>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs
new file mode 100644
index 00000000000..f7dc2fb8839
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs
@@ -0,0 +1,13 @@
+trait Foo<T> {
+    type Bar
+    where
+        Self: Foo<()>;
+}
+
+trait Cake {}
+impl Cake for () {}
+
+fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr
new file mode 100644
index 00000000000..815747436bf
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr
@@ -0,0 +1,21 @@
+error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+  --> $DIR/assoc_type_bounds2.rs:10:16
+   |
+LL |     type Bar
+   |     -------- `Bar` defined here
+...
+LL | fn foo(_: &dyn Foo<()>) {}
+   |                ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
+
+error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+  --> $DIR/assoc_type_bounds2.rs:11:16
+   |
+LL |     type Bar
+   |     -------- `Bar` defined here
+...
+LL | fn bar(_: &dyn Foo<i32>) {}
+   |                ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = Type>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed
new file mode 100644
index 00000000000..88697bad4d7
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed
@@ -0,0 +1,11 @@
+//@ run-rustfix
+#![allow(dead_code)]
+trait TraitWithAType {
+    type Item: ?Sized;
+}
+trait Trait {}
+struct A {}
+impl TraitWithAType for A {
+    type Item = dyn Trait; //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs
new file mode 100644
index 00000000000..944b296aa4d
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs
@@ -0,0 +1,11 @@
+//@ run-rustfix
+#![allow(dead_code)]
+trait TraitWithAType {
+    type Item;
+}
+trait Trait {}
+struct A {}
+impl TraitWithAType for A {
+    type Item = dyn Trait; //~ ERROR E0277
+}
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr
new file mode 100644
index 00000000000..9bb770ce431
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/assoc_type_bounds_implicit_sized.rs:9:17
+   |
+LL |     type Item = dyn Trait;
+   |                 ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+note: required by a bound in `TraitWithAType::Item`
+  --> $DIR/assoc_type_bounds_implicit_sized.rs:4:5
+   |
+LL |     type Item;
+   |     ^^^^^^^^^^ required by this bound in `TraitWithAType::Item`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Item: ?Sized;
+   |              ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs
new file mode 100644
index 00000000000..7535871afe5
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs
@@ -0,0 +1,24 @@
+//! This test checks that associated types only need to be
+//! mentioned in trait objects, if they don't require `Self: Sized`.
+
+//@ check-pass
+
+trait Foo {
+    type Bar
+    where
+        Self: Sized;
+}
+
+fn foo(_: &dyn Foo) {}
+
+trait Other: Sized {}
+
+trait Boo {
+    type Assoc
+    where
+        Self: Other;
+}
+
+fn boo(_: &dyn Boo) {}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs
new file mode 100644
index 00000000000..5b07bc92f32
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs
@@ -0,0 +1,25 @@
+//! This test checks that even if some associated types have
+//! `where Self: Sized` bounds, those without still need to be
+//! mentioned in trait objects.
+
+trait Foo {
+    type Bar
+    where
+        Self: Sized;
+    type Bop;
+}
+
+fn foo(_: &dyn Foo) {}
+//~^ ERROR the value of the associated type `Bop` in `Foo` must be specified
+
+trait Bar {
+    type Bop;
+    type Bar
+    where
+        Self: Sized;
+}
+
+fn bar(_: &dyn Bar) {}
+//~^ ERROR the value of the associated type `Bop` in `Bar` must be specified
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr
new file mode 100644
index 00000000000..5438faaaf05
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr
@@ -0,0 +1,21 @@
+error[E0191]: the value of the associated type `Bop` in `Foo` must be specified
+  --> $DIR/assoc_type_bounds_sized_others.rs:12:16
+   |
+LL |     type Bop;
+   |     -------- `Bop` defined here
+...
+LL | fn foo(_: &dyn Foo) {}
+   |                ^^^ help: specify the associated type: `Foo<Bop = Type>`
+
+error[E0191]: the value of the associated type `Bop` in `Bar` must be specified
+  --> $DIR/assoc_type_bounds_sized_others.rs:22:16
+   |
+LL |     type Bop;
+   |     -------- `Bop` defined here
+...
+LL | fn bar(_: &dyn Bar) {}
+   |                ^^^ help: specify the associated type: `Bar<Bop = Type>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs
new file mode 100644
index 00000000000..e9216da5927
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+
+trait Foo {
+    type Bar
+    where
+        Self: Sized;
+}
+
+fn foo(_: &dyn Foo<Bar = ()>) {}
+//~^ WARN: unnecessary associated type bound for dyn-incompatible associated type
+
+#[allow(unused_associated_type_bounds)]
+fn bar(_: &dyn Foo<Bar = ()>) {}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr
new file mode 100644
index 00000000000..aaadc4ed7b1
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr
@@ -0,0 +1,11 @@
+warning: unnecessary associated type bound for dyn-incompatible associated type
+  --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20
+   |
+LL | fn foo(_: &dyn Foo<Bar = ()>) {}
+   |                    ^^^^^^^^ help: remove this bound
+   |
+   = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`
+   = note: `#[warn(unused_associated_type_bounds)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs
new file mode 100644
index 00000000000..d59fc1712ea
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs
@@ -0,0 +1,18 @@
+//! This test checks that associated types with `Self: Sized` cannot be projected
+//! from a `dyn Trait`.
+
+trait Bop {
+    type Bar: Default
+    where
+        Self: Sized;
+}
+
+fn bop<T: Bop + ?Sized>() {
+    let _ = <T as Bop>::Bar::default();
+    //~^ ERROR: trait bounds were not satisfied
+    //~| ERROR: the size for values of type `T` cannot be known at compilation time
+}
+
+fn main() {
+    bop::<dyn Bop>();
+}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr
new file mode 100644
index 00000000000..b67a1244ece
--- /dev/null
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr
@@ -0,0 +1,44 @@
+error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied
+  --> $DIR/assoc_type_bounds_sized_used.rs:11:30
+   |
+LL |     let _ = <T as Bop>::Bar::default();
+   |                              ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `T: Sized`
+           which is required by `<T as Bop>::Bar: Default`
+help: consider restricting the type parameter to satisfy the trait bound
+   |
+LL | fn bop<T: Bop + ?Sized>() where T: Sized {
+   |                           ++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/assoc_type_bounds_sized_used.rs:11:14
+   |
+LL | fn bop<T: Bop + ?Sized>() {
+   |        - this type parameter needs to be `Sized`
+LL |     let _ = <T as Bop>::Bar::default();
+   |              ^ doesn't have a size known at compile-time
+   |
+note: required by a bound in `Bop::Bar`
+  --> $DIR/assoc_type_bounds_sized_used.rs:7:15
+   |
+LL |     type Bar: Default
+   |          --- required by a bound in this associated type
+LL |     where
+LL |         Self: Sized;
+   |               ^^^^^ required by this bound in `Bop::Bar`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn bop<T: Bop + ?Sized>() {
+LL + fn bop<T: Bop>() {
+   |
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Bar: Default + ?Sized
+   |                       ++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/dyn-compatibility/associated-consts.curr.stderr b/tests/ui/dyn-compatibility/associated-consts.curr.stderr
new file mode 100644
index 00000000000..17d184942c7
--- /dev/null
+++ b/tests/ui/dyn-compatibility/associated-consts.curr.stderr
@@ -0,0 +1,34 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/associated-consts.rs:12:31
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+   |                               ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/associated-consts.rs:9:11
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     const X: usize;
+   |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/associated-consts.rs:14:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/associated-consts.rs:9:11
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     const X: usize;
+   |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..cc5120232c2
--- /dev/null
+++ b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,19 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/associated-consts.rs:14:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/associated-consts.rs:9:11
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     const X: usize;
+   |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/associated-consts.rs b/tests/ui/dyn-compatibility/associated-consts.rs
new file mode 100644
index 00000000000..fc7b372b782
--- /dev/null
+++ b/tests/ui/dyn-compatibility/associated-consts.rs
@@ -0,0 +1,19 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with associated consts.
+//
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+trait Bar {
+    const X: usize;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t
+    //~^ ERROR E0038
+}
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr
new file mode 100644
index 00000000000..4e3d2ebebad
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr
@@ -0,0 +1,41 @@
+error[E0038]: the trait `Copy` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^ `Copy` cannot be made into an object
+   |
+   = note: the trait cannot be made into an object because it requires `Self: Sized`
+   = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
+error[E0618]: expected function, found `(dyn Copy + 'static)`
+  --> $DIR/avoid-ice-on-warning-2.rs:11:5
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |          - `f` has type `(dyn Copy + 'static)`
+...
+LL |     f()
+   |     ^--
+   |     |
+   |     call expression requires function
+
+error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn id<F>(f: impl Copy) -> usize {
+   |             ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn id<F>(f: &dyn Copy) -> usize {
+   |             ++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0277, E0618.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr
new file mode 100644
index 00000000000..180cd679dea
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr
@@ -0,0 +1,69 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | fn id<F>(f: dyn Copy) -> usize {
+   |             +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | fn id<F>(f: dyn Copy) -> usize {
+   |             +++
+
+error[E0038]: the trait `Copy` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^ `Copy` cannot be made into an object
+   |
+   = note: the trait cannot be made into an object because it requires `Self: Sized`
+   = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
+error[E0618]: expected function, found `(dyn Copy + 'static)`
+  --> $DIR/avoid-ice-on-warning-2.rs:11:5
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |          - `f` has type `(dyn Copy + 'static)`
+...
+LL |     f()
+   |     ^--
+   |     |
+   |     call expression requires function
+
+error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time
+  --> $DIR/avoid-ice-on-warning-2.rs:4:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn id<F>(f: impl Copy) -> usize {
+   |             ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn id<F>(f: &dyn Copy) -> usize {
+   |             ++++
+
+error: aborting due to 3 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0038, E0277, E0618.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs
new file mode 100644
index 00000000000..db2f4aea05b
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs
@@ -0,0 +1,14 @@
+//@ revisions: old new
+//@[old] edition:2015
+//@[new] edition:2021
+fn id<F>(f: Copy) -> usize {
+//~^ ERROR the trait `Copy` cannot be made into an object
+//~| ERROR: the size for values of type `(dyn Copy + 'static)`
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    f()
+    //~^ ERROR: expected function, found `(dyn Copy + 'static)`
+}
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr
new file mode 100644
index 00000000000..fdd3e8ab507
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr
@@ -0,0 +1,47 @@
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:4:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^ `A` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:12:14
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |       -      ^ ...because associated function `g` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `g` into a method by giving it a `&self` argument
+   |
+LL | trait A { fn g(&self, b: B) -> B; }
+   |                ++++++
+help: alternatively, consider constraining `g` so it does not apply to trait objects
+   |
+LL | trait A { fn g(b: B) -> B where Self: Sized; }
+   |                           +++++++++++++++++
+
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:12:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^ `B` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:4:14
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |       -      ^ ...because associated function `f` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `f` into a method by giving it a `&self` argument
+   |
+LL | trait B { fn f(&self, a: A) -> A; }
+   |                ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+   |
+LL | trait B { fn f(a: A) -> A where Self: Sized; }
+   |                           +++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr
new file mode 100644
index 00000000000..bd362abb355
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr
@@ -0,0 +1,128 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:4:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait B { fn f(a: dyn A) -> A; }
+   |                   +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:4:25
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                         ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait B { fn f(a: A) -> dyn A; }
+   |                         +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:12:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait A { fn g(b: dyn B) -> B; }
+   |                   +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:12:25
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                         ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait A { fn g(b: B) -> dyn B; }
+   |                         +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:4:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait B { fn f(a: dyn A) -> A; }
+   |                   +++
+
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:4:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^ `A` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:12:14
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |       -      ^ ...because associated function `g` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `g` into a method by giving it a `&self` argument
+   |
+LL | trait A { fn g(&self, b: B) -> B; }
+   |                ++++++
+help: alternatively, consider constraining `g` so it does not apply to trait objects
+   |
+LL | trait A { fn g(b: B) -> B where Self: Sized; }
+   |                           +++++++++++++++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:12:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | trait A { fn g(b: dyn B) -> B; }
+   |                   +++
+
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:12:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^ `B` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:4:14
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |       -      ^ ...because associated function `f` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `f` into a method by giving it a `&self` argument
+   |
+LL | trait B { fn f(&self, a: A) -> A; }
+   |                ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+   |
+LL | trait B { fn f(a: A) -> A where Self: Sized; }
+   |                           +++++++++++++++++
+
+error: aborting due to 2 previous errors; 6 warnings emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs
new file mode 100644
index 00000000000..38bee8142bb
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs
@@ -0,0 +1,20 @@
+//@ revisions: old new
+//@[old] edition:2015
+//@[new] edition:2021
+trait B { fn f(a: A) -> A; }
+//~^ ERROR the trait `A` cannot be made into an object
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN this is accepted in the current edition
+//[old]~| WARN this is accepted in the current edition
+//[old]~| WARN this is accepted in the current edition
+trait A { fn g(b: B) -> B; }
+//~^ ERROR the trait `B` cannot be made into an object
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN this is accepted in the current edition
+//[old]~| WARN this is accepted in the current edition
+//[old]~| WARN this is accepted in the current edition
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr
new file mode 100644
index 00000000000..4ff45d7a848
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr
@@ -0,0 +1,20 @@
+error: return types are denoted using `->`
+  --> $DIR/avoid-ice-on-warning.rs:4:23
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                       ^
+   |
+help: use `->` instead
+   |
+LL | fn call_this<F>(f: F) -> Fn(&str) + call_that {}
+   |                       ~~
+
+error[E0405]: cannot find trait `call_that` in this scope
+  --> $DIR/avoid-ice-on-warning.rs:4:36
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                                    ^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr
new file mode 100644
index 00000000000..646fb57af9e
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr
@@ -0,0 +1,34 @@
+error: return types are denoted using `->`
+  --> $DIR/avoid-ice-on-warning.rs:4:23
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                       ^
+   |
+help: use `->` instead
+   |
+LL | fn call_this<F>(f: F) -> Fn(&str) + call_that {}
+   |                       ~~
+
+error[E0405]: cannot find trait `call_that` in this scope
+  --> $DIR/avoid-ice-on-warning.rs:4:36
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                                    ^^^^^^^^^ not found in this scope
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning.rs:4:25
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | fn call_this<F>(f: F) : dyn Fn(&str) + call_that {}
+   |                         +++
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs
new file mode 100644
index 00000000000..b90d8911d50
--- /dev/null
+++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs
@@ -0,0 +1,9 @@
+//@ revisions: old new
+//@[old] edition:2015
+//@[new] edition:2021
+fn call_this<F>(f: F) : Fn(&str) + call_that {}
+//~^ ERROR return types are denoted using `->`
+//~| ERROR cannot find trait `call_that` in this scope
+//[old]~| WARN trait objects without an explicit `dyn` are deprecated
+//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed
new file mode 100644
index 00000000000..4f5310082e1
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed
@@ -0,0 +1,14 @@
+//@ revisions: old new
+//@[old] edition:2015
+//@[new] edition:2021
+//@[new] run-rustfix
+#![deny(bare_trait_objects)]
+fn ord_prefer_dot(s: String) -> impl Ord {
+    //~^ ERROR the trait `Ord` cannot be made into an object
+    //[old]~| ERROR trait objects without an explicit `dyn` are deprecated
+    //[old]~| WARNING this is accepted in the current edition (Rust 2015)
+    (s.starts_with("."), s)
+}
+fn main() {
+    let _ = ord_prefer_dot(String::new());
+}
diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr
new file mode 100644
index 00000000000..bb2bf6ddcda
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr
@@ -0,0 +1,21 @@
+error[E0038]: the trait `Ord` cannot be made into an object
+  --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33
+   |
+LL | fn ord_prefer_dot(s: String) -> Ord {
+   |                                 ^^^ `Ord` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | fn ord_prefer_dot(s: String) -> impl Ord {
+   |                                 ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr
new file mode 100644
index 00000000000..45c9b0ce5d9
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr
@@ -0,0 +1,39 @@
+error: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33
+   |
+LL | fn ord_prefer_dot(s: String) -> Ord {
+   |                                 ^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+note: the lint level is defined here
+  --> $DIR/bare-trait-dont-suggest-dyn.rs:5:9
+   |
+LL | #![deny(bare_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^
+help: if this is a dyn-compatible trait, use `dyn`
+   |
+LL | fn ord_prefer_dot(s: String) -> dyn Ord {
+   |                                 +++
+
+error[E0038]: the trait `Ord` cannot be made into an object
+  --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33
+   |
+LL | fn ord_prefer_dot(s: String) -> Ord {
+   |                                 ^^^ `Ord` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | fn ord_prefer_dot(s: String) -> impl Ord {
+   |                                 ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs
new file mode 100644
index 00000000000..cb5a305eab0
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs
@@ -0,0 +1,14 @@
+//@ revisions: old new
+//@[old] edition:2015
+//@[new] edition:2021
+//@[new] run-rustfix
+#![deny(bare_trait_objects)]
+fn ord_prefer_dot(s: String) -> Ord {
+    //~^ ERROR the trait `Ord` cannot be made into an object
+    //[old]~| ERROR trait objects without an explicit `dyn` are deprecated
+    //[old]~| WARNING this is accepted in the current edition (Rust 2015)
+    (s.starts_with("."), s)
+}
+fn main() {
+    let _ = ord_prefer_dot(String::new());
+}
diff --git a/tests/ui/dyn-compatibility/bounds.rs b/tests/ui/dyn-compatibility/bounds.rs
new file mode 100644
index 00000000000..1e04d11c516
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bounds.rs
@@ -0,0 +1,12 @@
+// Traits with bounds mentioning `Self` are dyn-incompatible.
+
+trait X {
+    type U: PartialEq<Self>;
+}
+
+fn f() -> Box<dyn X<U = u32>> {
+    //~^ ERROR the trait `X` cannot be made into an object
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/bounds.stderr b/tests/ui/dyn-compatibility/bounds.stderr
new file mode 100644
index 00000000000..9231d524fd1
--- /dev/null
+++ b/tests/ui/dyn-compatibility/bounds.stderr
@@ -0,0 +1,17 @@
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/bounds.rs:7:15
+   |
+LL | fn f() -> Box<dyn X<U = u32>> {
+   |               ^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/bounds.rs:4:13
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
+LL |     type U: PartialEq<Self>;
+   |             ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/by-value-self-use.rs b/tests/ui/dyn-compatibility/by-value-self-use.rs
new file mode 100644
index 00000000000..3c04ec0cd88
--- /dev/null
+++ b/tests/ui/dyn-compatibility/by-value-self-use.rs
@@ -0,0 +1,18 @@
+// Check that while a trait with by-value self is dyn-compatible, we
+// can't actually invoke it from an object (yet...?).
+
+#![feature(rustc_attrs)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+fn use_bar(t: Box<dyn Bar>) {
+    t.bar() //~ ERROR cannot move a value of type `dyn Bar`
+}
+
+fn main() { }
diff --git a/tests/ui/dyn-compatibility/by-value-self-use.stderr b/tests/ui/dyn-compatibility/by-value-self-use.stderr
new file mode 100644
index 00000000000..14785b982a3
--- /dev/null
+++ b/tests/ui/dyn-compatibility/by-value-self-use.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type `dyn Bar`
+  --> $DIR/by-value-self-use.rs:15:5
+   |
+LL |     t.bar()
+   |     ^ the size of `dyn Bar` cannot be statically determined
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/tests/ui/dyn-compatibility/by-value-self.rs b/tests/ui/dyn-compatibility/by-value-self.rs
new file mode 100644
index 00000000000..a057a7ff0b5
--- /dev/null
+++ b/tests/ui/dyn-compatibility/by-value-self.rs
@@ -0,0 +1,46 @@
+// Check that a trait with by-value self is considered dyn-compatible.
+
+//@ build-pass (FIXME(62277): could be check-pass?)
+#![allow(dead_code)]
+#![allow(trivial_casts)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+trait Quux {
+    // Legal because of the where clause:
+    fn baz(self: Self) where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+    t // legal
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
+    t as &dyn Bar // legal
+}
+
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+    t // legal
+}
+
+fn make_baz_explicit<T:Baz>(t: &T) -> &dyn Baz {
+    t as &dyn Baz // legal
+}
+
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+    t as &dyn Quux
+}
+
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs b/tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs
new file mode 100644
index 00000000000..7a3a7f3ca2f
--- /dev/null
+++ b/tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+trait Foo {
+    type Bar<'a>
+    where
+        Self: Sized;
+
+    fn test(&self);
+}
+
+impl Foo for () {
+    type Bar<'a> = () where Self: Sized;
+
+    fn test(&self) {}
+}
+
+fn test(x: &dyn Foo) {
+    x.test();
+}
+
+fn main() {
+    test(&());
+}
diff --git a/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs
new file mode 100644
index 00000000000..d3c3963a673
--- /dev/null
+++ b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+// issue: rust-lang/rust#102933
+
+use std::future::Future;
+
+pub trait Service {
+    type Response;
+    type Future: Future<Output = Self::Response>;
+}
+
+pub trait A1: Service<Response = i32> {}
+
+pub trait A2: Service<Future = Box<dyn Future<Output = i32>>> + A1 {
+    fn foo(&self) {}
+}
+
+pub trait B1: Service<Future = Box<dyn Future<Output = i32>>> {}
+
+pub trait B2: Service<Response = i32> + B1 {
+    fn foo(&self) {}
+}
+
+fn main() {
+    let x: &dyn A2 = todo!();
+    let x: &dyn B2 = todo!();
+}
diff --git a/tests/ui/dyn-compatibility/erroneous_signature.rs b/tests/ui/dyn-compatibility/erroneous_signature.rs
new file mode 100644
index 00000000000..cc1841cc4b2
--- /dev/null
+++ b/tests/ui/dyn-compatibility/erroneous_signature.rs
@@ -0,0 +1,17 @@
+trait Foo {
+    fn err(&self) -> MissingType;
+    //~^ ERROR cannot find type `MissingType` in this scope
+}
+
+impl Foo for i32 {
+    fn err(&self) -> MissingType {
+        //~^ ERROR cannot find type `MissingType` in this scope
+        0
+    }
+}
+
+fn coerce(x: &i32) -> &dyn Foo {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/erroneous_signature.stderr b/tests/ui/dyn-compatibility/erroneous_signature.stderr
new file mode 100644
index 00000000000..f3b14ffe34c
--- /dev/null
+++ b/tests/ui/dyn-compatibility/erroneous_signature.stderr
@@ -0,0 +1,15 @@
+error[E0412]: cannot find type `MissingType` in this scope
+  --> $DIR/erroneous_signature.rs:2:22
+   |
+LL |     fn err(&self) -> MissingType;
+   |                      ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType` in this scope
+  --> $DIR/erroneous_signature.rs:7:22
+   |
+LL |     fn err(&self) -> MissingType {
+   |                      ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/dyn-compatibility/generics.curr.stderr b/tests/ui/dyn-compatibility/generics.curr.stderr
new file mode 100644
index 00000000000..c63db38a080
--- /dev/null
+++ b/tests/ui/dyn-compatibility/generics.curr.stderr
@@ -0,0 +1,80 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:18:31
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+   |                               ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:25:40
+   |
+LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
+   |                                        ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:20:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:27:10
+   |
+LL |     t as &dyn Bar
+   |          ^^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:27:5
+   |
+LL |     t as &dyn Bar
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..ba2546ef2dc
--- /dev/null
+++ b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,35 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:20:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/generics.rs:27:5
+   |
+LL |     t as &dyn Bar
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/generics.rs:10:8
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar<T>(&self, t: T);
+   |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/generics.rs b/tests/ui/dyn-compatibility/generics.rs
new file mode 100644
index 00000000000..b51555aa500
--- /dev/null
+++ b/tests/ui/dyn-compatibility/generics.rs
@@ -0,0 +1,42 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with generic methods, unless `where Self : Sized` is
+// present.
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+
+trait Bar {
+    fn bar<T>(&self, t: T);
+}
+
+trait Quux {
+    fn bar<T>(&self, t: T)
+        where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t
+    //[dyn_compatible_for_dispatch]~^ ERROR E0038
+    //[curr]~^^ ERROR E0038
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t as &dyn Bar
+    //[dyn_compatible_for_dispatch]~^ ERROR E0038
+    //[curr]~^^ ERROR E0038
+    //[curr]~| ERROR E0038
+}
+
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+    t as &dyn Quux
+}
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs
new file mode 100644
index 00000000000..c2b8ecc141d
--- /dev/null
+++ b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+// issue: rust-lang/rust#106247
+
+pub trait Trait {
+    fn method(&self) where Self: Sync;
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs b/tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs
new file mode 100644
index 00000000000..4ae982e8f95
--- /dev/null
+++ b/tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+
+pub trait Foo {
+    type X: PartialEq;
+    type Y: PartialEq<Self::Y>;
+    type Z: PartialEq<Self::Y>;
+}
+
+fn uwu(x: &dyn Foo<X = i32, Y = i32, Z = i32>) {}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs
new file mode 100644
index 00000000000..1289d2d7874
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs
@@ -0,0 +1,22 @@
+// issue: rust-lang/rust#19538
+
+trait Foo {
+    fn foo<T>(&self, val: T);
+}
+
+trait Bar: Foo { }
+
+pub struct Thing;
+
+impl Foo for Thing {
+    fn foo<T>(&self, val: T) { }
+}
+
+impl Bar for Thing { }
+
+fn main() {
+    let mut thing = Thing;
+    let test: &mut dyn Bar = &mut thing;
+    //~^ ERROR E0038
+    //~| ERROR E0038
+}
diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
new file mode 100644
index 00000000000..7378ec023c9
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
@@ -0,0 +1,38 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15
+   |
+LL |     let test: &mut dyn Bar = &mut thing;
+   |               ^^^^^^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
+   |
+LL |     fn foo<T>(&self, val: T);
+   |        ^^^ ...because method `foo` has generic type parameters
+...
+LL | trait Bar: Foo { }
+   |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30
+   |
+LL |     let test: &mut dyn Bar = &mut thing;
+   |                              ^^^^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
+   |
+LL |     fn foo<T>(&self, val: T);
+   |        ^^^ ...because method `foo` has generic type parameters
+...
+LL | trait Bar: Foo { }
+   |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
+   = note: required for the cast from `&mut Thing` to `&mut dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs
new file mode 100644
index 00000000000..c9ec44cc0b8
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs
@@ -0,0 +1,44 @@
+// Regression test for #22040.
+
+use std::fmt::Debug;
+
+trait Expr: Debug + PartialEq {
+    fn print_element_count(&self);
+}
+
+//#[derive(PartialEq)]
+#[derive(Debug)]
+struct SExpr<'x> {
+    elements: Vec<Box<dyn Expr + 'x>>,
+    //~^ ERROR E0038
+}
+
+impl<'x> PartialEq for SExpr<'x> {
+    fn eq(&self, other:&SExpr<'x>) -> bool {
+        println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
+
+        let result = self.elements.len() == other.elements.len();
+
+        println!("Got compare {}", result);
+        return result;
+    }
+}
+
+impl <'x> SExpr<'x> {
+    fn new() -> SExpr<'x> { return SExpr{elements: Vec::new(),}; }
+}
+
+impl <'x> Expr for SExpr<'x> {
+    fn print_element_count(&self) {
+        println!("element count: {}", self.elements.len());
+    }
+}
+
+fn main() {
+    let a: Box<dyn Expr> = Box::new(SExpr::new());
+    //~^ ERROR: `Expr` cannot be made into an object
+    let b: Box<dyn Expr> = Box::new(SExpr::new());
+    //~^ ERROR: `Expr` cannot be made into an object
+
+    // assert_eq!(a , b);
+}
diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr
new file mode 100644
index 00000000000..7578edce7d1
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr
@@ -0,0 +1,48 @@
+error[E0038]: the trait `Expr` cannot be made into an object
+  --> $DIR/mentions-Self-in-super-predicates.rs:12:23
+   |
+LL |     elements: Vec<Box<dyn Expr + 'x>>,
+   |                       ^^^^^^^^^^^^^ `Expr` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self-in-super-predicates.rs:5:21
+   |
+LL | trait Expr: Debug + PartialEq {
+   |       ----          ^^^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+   = help: only type `SExpr<'x>` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Expr` cannot be made into an object
+  --> $DIR/mentions-Self-in-super-predicates.rs:38:16
+   |
+LL |     let a: Box<dyn Expr> = Box::new(SExpr::new());
+   |                ^^^^^^^^ `Expr` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self-in-super-predicates.rs:5:21
+   |
+LL | trait Expr: Debug + PartialEq {
+   |       ----          ^^^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+   = help: only type `SExpr<'x>` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Expr` cannot be made into an object
+  --> $DIR/mentions-Self-in-super-predicates.rs:40:16
+   |
+LL |     let b: Box<dyn Expr> = Box::new(SExpr::new());
+   |                ^^^^^^^^ `Expr` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self-in-super-predicates.rs:5:21
+   |
+LL | trait Expr: Debug + PartialEq {
+   |       ----          ^^^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+   = help: only type `SExpr<'x>` implements the trait, consider using it directly instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mentions-Self.curr.stderr b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr
new file mode 100644
index 00000000000..434e41cf218
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr
@@ -0,0 +1,65 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/mentions-Self.rs:22:31
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+   |                               ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:11:22
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar(&self, x: &Self);
+   |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/mentions-Self.rs:28:31
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+   |                               ^^^^^^^ `Baz` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:15:22
+   |
+LL | trait Baz {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> Self;
+   |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/mentions-Self.rs:24:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:11:22
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar(&self, x: &Self);
+   |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/mentions-Self.rs:30:5
+   |
+LL |     t
+   |     ^ `Baz` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:15:22
+   |
+LL | trait Baz {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> Self;
+   |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
+   = note: required for the cast from `&T` to `&dyn Baz`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..dc2d1f87eb7
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,35 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/mentions-Self.rs:24:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:11:22
+   |
+LL | trait Bar {
+   |       --- this trait cannot be made into an object...
+LL |     fn bar(&self, x: &Self);
+   |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/mentions-Self.rs:30:5
+   |
+LL |     t
+   |     ^ `Baz` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/mentions-Self.rs:15:22
+   |
+LL | trait Baz {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> Self;
+   |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
+   = note: required for the cast from `&T` to `&dyn Baz`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mentions-Self.rs b/tests/ui/dyn-compatibility/mentions-Self.rs
new file mode 100644
index 00000000000..84c229e252d
--- /dev/null
+++ b/tests/ui/dyn-compatibility/mentions-Self.rs
@@ -0,0 +1,42 @@
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return
+// position, unless `where Self : Sized` is present..
+//
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+
+trait Bar {
+    fn bar(&self, x: &Self);
+}
+
+trait Baz {
+    fn baz(&self) -> Self;
+}
+
+trait Quux {
+    fn quux(&self, s: &Self) -> Self where Self : Sized;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t
+    //~^ ERROR E0038
+}
+
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+    //[curr]~^ ERROR E0038
+    t
+    //~^ ERROR E0038
+}
+
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+    t as &dyn Quux
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs
new file mode 100644
index 00000000000..c83be544c0a
--- /dev/null
+++ b/tests/ui/dyn-compatibility/missing-assoc-type.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    type Bar<T>;
+}
+
+fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` cannot be made into an object
+//~^ ERROR the trait `Foo` cannot be made into an object
+//~| ERROR the trait `Foo` cannot be made into an object
+//~| ERROR the trait `Foo` cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr
new file mode 100644
index 00000000000..f8450ba212d
--- /dev/null
+++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr
@@ -0,0 +1,65 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/missing-assoc-type.rs:5:16
+   |
+LL | fn bar(x: &dyn Foo) {}
+   |                ^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/missing-assoc-type.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Bar<T>;
+   |          ^^^ ...because it contains the generic associated type `Bar`
+   = help: consider moving `Bar` to another trait
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/missing-assoc-type.rs:5:16
+   |
+LL | fn bar(x: &dyn Foo) {}
+   |                ^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/missing-assoc-type.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Bar<T>;
+   |          ^^^ ...because it contains the generic associated type `Bar`
+   = help: consider moving `Bar` to another trait
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/missing-assoc-type.rs:5:16
+   |
+LL | fn bar(x: &dyn Foo) {}
+   |                ^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/missing-assoc-type.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Bar<T>;
+   |          ^^^ ...because it contains the generic associated type `Bar`
+   = help: consider moving `Bar` to another trait
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/missing-assoc-type.rs:5:12
+   |
+LL | fn bar(x: &dyn Foo) {}
+   |            ^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/missing-assoc-type.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Bar<T>;
+   |          ^^^ ...because it contains the generic associated type `Bar`
+   = help: consider moving `Bar` to another trait
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/no-static.curr.stderr b/tests/ui/dyn-compatibility/no-static.curr.stderr
new file mode 100644
index 00000000000..584db779855
--- /dev/null
+++ b/tests/ui/dyn-compatibility/no-static.curr.stderr
@@ -0,0 +1,73 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/no-static.rs:12:22
+   |
+LL | fn diverges() -> Box<dyn Foo> {
+   |                      ^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/no-static.rs:9:8
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn foo() {}
+   |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
+help: consider turning `foo` into a method by giving it a `&self` argument
+   |
+LL |     fn foo(&self) {}
+   |            +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+   |
+LL |     fn foo() where Self: Sized {}
+   |              +++++++++++++++++
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/no-static.rs:22:12
+   |
+LL |     let b: Box<dyn Foo> = Box::new(Bar);
+   |            ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/no-static.rs:9:8
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn foo() {}
+   |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
+help: consider turning `foo` into a method by giving it a `&self` argument
+   |
+LL |     fn foo(&self) {}
+   |            +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+   |
+LL |     fn foo() where Self: Sized {}
+   |              +++++++++++++++++
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/no-static.rs:22:27
+   |
+LL |     let b: Box<dyn Foo> = Box::new(Bar);
+   |                           ^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/no-static.rs:9:8
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn foo() {}
+   |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
+   = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
+help: consider turning `foo` into a method by giving it a `&self` argument
+   |
+LL |     fn foo(&self) {}
+   |            +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+   |
+LL |     fn foo() where Self: Sized {}
+   |              +++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..f2deb3b8d84
--- /dev/null
+++ b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,27 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/no-static.rs:22:27
+   |
+LL |     let b: Box<dyn Foo> = Box::new(Bar);
+   |                           ^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/no-static.rs:9:8
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn foo() {}
+   |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
+   = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
+help: consider turning `foo` into a method by giving it a `&self` argument
+   |
+LL |     fn foo(&self) {}
+   |            +++++
+help: alternatively, consider constraining `foo` so it does not apply to trait objects
+   |
+LL |     fn foo() where Self: Sized {}
+   |              +++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/no-static.rs b/tests/ui/dyn-compatibility/no-static.rs
new file mode 100644
index 00000000000..54af16fe18e
--- /dev/null
+++ b/tests/ui/dyn-compatibility/no-static.rs
@@ -0,0 +1,25 @@
+// Check that we correctly prevent users from making trait objects
+// from traits with static methods.
+//
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+trait Foo {
+    fn foo() {}
+}
+
+fn diverges() -> Box<dyn Foo> {
+    //[curr]~^ ERROR E0038
+    loop { }
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+
+fn main() {
+    let b: Box<dyn Foo> = Box::new(Bar);
+    //~^ ERROR E0038
+    //[curr]~| ERROR E0038
+}
diff --git a/tests/ui/dyn-compatibility/phantom-fn.rs b/tests/ui/dyn-compatibility/phantom-fn.rs
new file mode 100644
index 00000000000..9e410da82ee
--- /dev/null
+++ b/tests/ui/dyn-compatibility/phantom-fn.rs
@@ -0,0 +1,22 @@
+// Check that `Self` appearing in a phantom fn does not make a trait dyn-incompatible.
+
+//@ build-pass (FIXME(62277): could be check-pass?)
+#![allow(dead_code)]
+
+trait Baz {
+}
+
+trait Bar<T> {
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> {
+    t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+    t
+}
+
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs
new file mode 100644
index 00000000000..dabaa309c16
--- /dev/null
+++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs
@@ -0,0 +1,142 @@
+//@ edition:2021
+
+trait Trait {}
+
+struct IceCream;
+
+impl IceCream {
+    fn foo(_: &Trait) {}
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn bar(self, _: &'a Trait) {}
+    //~^ ERROR: trait objects must include the `dyn` keyword
+    //~| ERROR: use of undeclared lifetime name
+
+    fn alice<'a>(&self, _: &Trait) {}
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn bob<'a>(_: &'a Trait) {}
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn cat() -> &Trait {
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn dog<'a>() -> &Trait {
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn kitten() -> &'a Trait {
+        //~^ ERROR: use of undeclared lifetime name
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn puppy<'a>() -> &'a Trait {
+        //~^ ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn parrot() -> &mut Trait {
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &mut Type
+        //~^ ERROR: cannot return reference to temporary value
+    }
+}
+
+trait Sing {
+    fn foo(_: &Trait);
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn bar(_: &'a Trait);
+    //~^ ERROR: trait objects must include the `dyn` keyword
+    //~| ERROR: use of undeclared lifetime name
+
+    fn alice<'a>(_: &Trait);
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn bob<'a>(_: &'a Trait);
+    //~^ ERROR: trait objects must include the `dyn` keyword
+
+    fn cat() -> &Trait;
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+
+    fn dog<'a>() -> &Trait {
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn kitten() -> &'a Trait {
+        //~^ ERROR: use of undeclared lifetime name
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn puppy<'a>() -> &'a Trait {
+        //~^ ERROR: trait objects must include the `dyn` keyword
+        &Type
+    }
+
+    fn parrot() -> &mut Trait {
+        //~^ ERROR: missing lifetime specifier
+        //~| ERROR: trait objects must include the `dyn` keyword
+        &mut Type
+        //~^ ERROR: cannot return reference to temporary value
+    }
+}
+
+fn foo(_: &Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+fn bar(_: &'a Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+//~| ERROR: use of undeclared lifetime name
+
+fn alice<'a>(_: &Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+fn bob<'a>(_: &'a Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+struct Type;
+
+impl Trait for Type {}
+
+fn cat() -> &Trait {
+//~^ ERROR: missing lifetime specifier
+//~| ERROR: trait objects must include the `dyn` keyword
+    &Type
+}
+
+fn dog<'a>() -> &Trait {
+//~^ ERROR: missing lifetime specifier
+//~| ERROR: trait objects must include the `dyn` keyword
+    &Type
+}
+
+fn kitten() -> &'a Trait {
+//~^ ERROR: use of undeclared lifetime name
+//~| ERROR: trait objects must include the `dyn` keyword
+    &Type
+}
+
+fn puppy<'a>() -> &'a Trait {
+//~^ ERROR: trait objects must include the `dyn` keyword
+    &Type
+}
+
+fn parrot() -> &mut Trait {
+    //~^ ERROR: missing lifetime specifier
+    //~| ERROR: trait objects must include the `dyn` keyword
+    &mut Type
+    //~^ ERROR: cannot return reference to temporary value
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr
new file mode 100644
index 00000000000..8bdfea7766e
--- /dev/null
+++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr
@@ -0,0 +1,673 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:22
+   |
+LL |     fn bar(self, _: &'a Trait) {}
+   |                      ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn bar<'a>(self, _: &'a Trait) {}
+   |           ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> IceCream {
+   |     ++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:17
+   |
+LL |     fn cat() -> &Trait {
+   |                 ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL |     fn cat() -> &'static Trait {
+   |                  +++++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:21
+   |
+LL |     fn dog<'a>() -> &Trait {
+   |                     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+   |
+LL |     fn dog<'a>() -> &'a Trait {
+   |                      ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:21
+   |
+LL |     fn kitten() -> &'a Trait {
+   |                     ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn kitten<'a>() -> &'a Trait {
+   |              ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> IceCream {
+   |     ++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:20
+   |
+LL |     fn parrot() -> &mut Trait {
+   |                    ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL |     fn parrot() -> &'static mut Trait {
+   |                     +++++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:16
+   |
+LL |     fn bar(_: &'a Trait);
+   |                ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn bar<'a>(_: &'a Trait);
+   |           ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait Sing<'a> {
+   |           ++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:17
+   |
+LL |     fn cat() -> &Trait;
+   |                 ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL |     fn cat() -> &'static Trait;
+   |                  +++++++
+help: instead, you are more likely to want to return an owned value
+   |
+LL -     fn cat() -> &Trait;
+LL +     fn cat() -> Trait;
+   |
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:21
+   |
+LL |     fn dog<'a>() -> &Trait {
+   |                     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+   |
+LL |     fn dog<'a>() -> &'a Trait {
+   |                      ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:21
+   |
+LL |     fn kitten() -> &'a Trait {
+   |                     ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn kitten<'a>() -> &'a Trait {
+   |              ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait Sing<'a> {
+   |           ++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:20
+   |
+LL |     fn parrot() -> &mut Trait {
+   |                    ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL |     fn parrot() -> &'static mut Trait {
+   |                     +++++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:12
+   |
+LL | fn bar(_: &'a Trait) {}
+   |       -    ^^ undeclared lifetime
+   |       |
+   |       help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:13
+   |
+LL | fn cat() -> &Trait {
+   |             ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL | fn cat() -> &'static Trait {
+   |              +++++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:17
+   |
+LL | fn dog<'a>() -> &Trait {
+   |                 ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+   |
+LL | fn dog<'a>() -> &'a Trait {
+   |                  ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:17
+   |
+LL | fn kitten() -> &'a Trait {
+   |          -      ^^ undeclared lifetime
+   |          |
+   |          help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:16
+   |
+LL | fn parrot() -> &mut Trait {
+   |                ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+   |
+LL | fn parrot() -> &'static mut Trait {
+   |                 +++++++
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:47:9
+   |
+LL |         &mut Type
+   |         ^^^^^----
+   |         |    |
+   |         |    temporary value created here
+   |         returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:90:9
+   |
+LL |         &mut Type
+   |         ^^^^^----
+   |         |    |
+   |         |    temporary value created here
+   |         returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:138:5
+   |
+LL |     &mut Type
+   |     ^^^^^----
+   |     |    |
+   |     |    temporary value created here
+   |     returns a reference to data owned by the current function
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:53:16
+   |
+LL |     fn foo(_: &Trait);
+   |                ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn foo<T: Trait>(_: &T);
+   |           ++++++++++     ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn foo(_: &impl Trait);
+   |                ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn foo(_: &dyn Trait);
+   |                +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:19
+   |
+LL |     fn bar(_: &'a Trait);
+   |                   ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn bar<T: Trait>(_: &'a T);
+   |           ++++++++++        ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn bar(_: &'a impl Trait);
+   |                   ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn bar(_: &'a dyn Trait);
+   |                   +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:60:22
+   |
+LL |     fn alice<'a>(_: &Trait);
+   |                      ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn alice<'a, T: Trait>(_: &T);
+   |                ++++++++++      ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn alice<'a>(_: &impl Trait);
+   |                      ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn alice<'a>(_: &dyn Trait);
+   |                      +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:63:23
+   |
+LL |     fn bob<'a>(_: &'a Trait);
+   |                       ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn bob<'a, T: Trait>(_: &'a T);
+   |              ++++++++++         ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn bob<'a>(_: &'a impl Trait);
+   |                       ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn bob<'a>(_: &'a dyn Trait);
+   |                       +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:18
+   |
+LL |     fn cat() -> &Trait;
+   |                  ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn cat() -> &impl Trait;
+   |                  ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn cat() -> Box<dyn Trait>;
+   |                 ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:22
+   |
+LL |     fn dog<'a>() -> &Trait {
+   |                      ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn dog<'a>() -> &impl Trait {
+   |                      ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn dog<'a>() -> Box<dyn Trait> {
+   |                     ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:24
+   |
+LL |     fn kitten() -> &'a Trait {
+   |                        ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn kitten() -> &'a impl Trait {
+   |                        ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn kitten() -> Box<dyn Trait> {
+   |                    ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:82:27
+   |
+LL |     fn puppy<'a>() -> &'a Trait {
+   |                           ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn puppy<'a>() -> &'a impl Trait {
+   |                           ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn puppy<'a>() -> Box<dyn Trait> {
+   |                       ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25
+   |
+LL |     fn parrot() -> &mut Trait {
+   |                         ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn parrot() -> &mut impl Trait {
+   |                         ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn parrot() -> Box<dyn Trait> {
+   |                    ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:95:12
+   |
+LL | fn foo(_: &Trait) {}
+   |            ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL | fn foo<T: Trait>(_: &T) {}
+   |       ++++++++++     ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn foo(_: &impl Trait) {}
+   |            ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL | fn foo(_: &dyn Trait) {}
+   |            +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:15
+   |
+LL | fn bar(_: &'a Trait) {}
+   |               ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL | fn bar<T: Trait>(_: &'a T) {}
+   |       ++++++++++        ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn bar(_: &'a impl Trait) {}
+   |               ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL | fn bar(_: &'a dyn Trait) {}
+   |               +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:102:18
+   |
+LL | fn alice<'a>(_: &Trait) {}
+   |                  ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL | fn alice<'a, T: Trait>(_: &T) {}
+   |            ++++++++++      ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn alice<'a>(_: &impl Trait) {}
+   |                  ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL | fn alice<'a>(_: &dyn Trait) {}
+   |                  +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:105:19
+   |
+LL | fn bob<'a>(_: &'a Trait) {}
+   |                   ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL | fn bob<'a, T: Trait>(_: &'a T) {}
+   |          ++++++++++         ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn bob<'a>(_: &'a impl Trait) {}
+   |                   ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL | fn bob<'a>(_: &'a dyn Trait) {}
+   |                   +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:14
+   |
+LL | fn cat() -> &Trait {
+   |              ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn cat() -> &impl Trait {
+   |              ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn cat() -> Box<dyn Trait> {
+   |             ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:18
+   |
+LL | fn dog<'a>() -> &Trait {
+   |                  ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn dog<'a>() -> &impl Trait {
+   |                  ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn dog<'a>() -> Box<dyn Trait> {
+   |                 ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:20
+   |
+LL | fn kitten() -> &'a Trait {
+   |                    ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn kitten() -> &'a impl Trait {
+   |                    ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn kitten() -> Box<dyn Trait> {
+   |                ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:130:23
+   |
+LL | fn puppy<'a>() -> &'a Trait {
+   |                       ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn puppy<'a>() -> &'a impl Trait {
+   |                       ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn puppy<'a>() -> Box<dyn Trait> {
+   |                   ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21
+   |
+LL | fn parrot() -> &mut Trait {
+   |                     ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn parrot() -> &mut impl Trait {
+   |                     ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn parrot() -> Box<dyn Trait> {
+   |                ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:8:16
+   |
+LL |     fn foo(_: &Trait) {}
+   |                ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn foo<T: Trait>(_: &T) {}
+   |           ++++++++++     ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn foo(_: &impl Trait) {}
+   |                ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn foo(_: &dyn Trait) {}
+   |                +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:25
+   |
+LL |     fn bar(self, _: &'a Trait) {}
+   |                         ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn bar<T: Trait>(self, _: &'a T) {}
+   |           ++++++++++              ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn bar(self, _: &'a impl Trait) {}
+   |                         ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn bar(self, _: &'a dyn Trait) {}
+   |                         +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:15:29
+   |
+LL |     fn alice<'a>(&self, _: &Trait) {}
+   |                             ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn alice<'a, T: Trait>(&self, _: &T) {}
+   |                ++++++++++             ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn alice<'a>(&self, _: &impl Trait) {}
+   |                             ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn alice<'a>(&self, _: &dyn Trait) {}
+   |                             +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:18:23
+   |
+LL |     fn bob<'a>(_: &'a Trait) {}
+   |                       ^^^^^
+   |
+help: use a new generic type parameter, constrained by `Trait`
+   |
+LL |     fn bob<'a, T: Trait>(_: &'a T) {}
+   |              ++++++++++         ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn bob<'a>(_: &'a impl Trait) {}
+   |                       ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn bob<'a>(_: &'a dyn Trait) {}
+   |                       +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:18
+   |
+LL |     fn cat() -> &Trait {
+   |                  ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn cat() -> &impl Trait {
+   |                  ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn cat() -> Box<dyn Trait> {
+   |                 ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:22
+   |
+LL |     fn dog<'a>() -> &Trait {
+   |                      ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn dog<'a>() -> &impl Trait {
+   |                      ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn dog<'a>() -> Box<dyn Trait> {
+   |                     ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:24
+   |
+LL |     fn kitten() -> &'a Trait {
+   |                        ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn kitten() -> &'a impl Trait {
+   |                        ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn kitten() -> Box<dyn Trait> {
+   |                    ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:39:27
+   |
+LL |     fn puppy<'a>() -> &'a Trait {
+   |                           ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn puppy<'a>() -> &'a impl Trait {
+   |                           ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn puppy<'a>() -> Box<dyn Trait> {
+   |                       ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25
+   |
+LL |     fn parrot() -> &mut Trait {
+   |                         ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn parrot() -> &mut impl Trait {
+   |                         ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn parrot() -> Box<dyn Trait> {
+   |                    ~~~~~~~~~~~~~~
+
+error: aborting due to 45 previous errors
+
+Some errors have detailed explanations: E0106, E0261, E0515, E0782.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/dyn-compatibility/sized-2.curr.stderr b/tests/ui/dyn-compatibility/sized-2.curr.stderr
new file mode 100644
index 00000000000..1017fde53d3
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized-2.curr.stderr
@@ -0,0 +1,32 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized-2.rs:14:31
+   |
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+   |                               ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized-2.rs:9:18
+   |
+LL | trait Bar
+   |       --- this trait cannot be made into an object...
+LL |     where Self : Sized
+   |                  ^^^^^ ...because it requires `Self: Sized`
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized-2.rs:16:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized-2.rs:9:18
+   |
+LL | trait Bar
+   |       --- this trait cannot be made into an object...
+LL |     where Self : Sized
+   |                  ^^^^^ ...because it requires `Self: Sized`
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..534cf0f1b03
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized-2.rs:16:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized-2.rs:9:18
+   |
+LL | trait Bar
+   |       --- this trait cannot be made into an object...
+LL |     where Self : Sized
+   |                  ^^^^^ ...because it requires `Self: Sized`
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized-2.rs b/tests/ui/dyn-compatibility/sized-2.rs
new file mode 100644
index 00000000000..f5edd287f24
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized-2.rs
@@ -0,0 +1,21 @@
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+//
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+trait Bar
+    where Self : Sized
+{
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t
+    //~^ ERROR E0038
+}
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/sized.curr.stderr b/tests/ui/dyn-compatibility/sized.curr.stderr
new file mode 100644
index 00000000000..613833aad12
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized.curr.stderr
@@ -0,0 +1,32 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized.rs:12:32
+   |
+LL | fn make_bar<T: Bar>(t: &T) -> &dyn Bar {
+   |                                ^^^^^^^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized.rs:8:12
+   |
+LL | trait Bar: Sized {
+   |       ---  ^^^^^ ...because it requires `Self: Sized`
+   |       |
+   |       this trait cannot be made into an object...
+
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized.rs:14:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized.rs:8:12
+   |
+LL | trait Bar: Sized {
+   |       ---  ^^^^^ ...because it requires `Self: Sized`
+   |       |
+   |       this trait cannot be made into an object...
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr
new file mode 100644
index 00000000000..cf847bc1577
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/sized.rs:14:5
+   |
+LL |     t
+   |     ^ `Bar` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/sized.rs:8:12
+   |
+LL | trait Bar: Sized {
+   |       ---  ^^^^^ ...because it requires `Self: Sized`
+   |       |
+   |       this trait cannot be made into an object...
+   = note: required for the cast from `&T` to `&dyn Bar`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized.rs b/tests/ui/dyn-compatibility/sized.rs
new file mode 100644
index 00000000000..4c4fe3f8f25
--- /dev/null
+++ b/tests/ui/dyn-compatibility/sized.rs
@@ -0,0 +1,18 @@
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+//
+//@ revisions: curr dyn_compatible_for_dispatch
+
+#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
+
+trait Bar: Sized {
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T: Bar>(t: &T) -> &dyn Bar {
+    //[curr]~^ ERROR E0038
+    t
+    //~^ ERROR E0038
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs
new file mode 100644
index 00000000000..14e00d2ef32
--- /dev/null
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs
@@ -0,0 +1,15 @@
+//~ ERROR the parameter type `Self` may not live long enough
+
+trait GatTrait {
+    type Gat<'a>
+    where
+        Self: 'a;
+}
+
+trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+    fn c(&self) -> dyn SuperTrait<T>;
+    //~^ ERROR associated item referring to unboxed trait object for its own trait
+    //~| ERROR the trait `SuperTrait` cannot be made into an object
+}
+
+fn main() {}
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr
new file mode 100644
index 00000000000..ac5a5b28d94
--- /dev/null
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr
@@ -0,0 +1,42 @@
+error[E0311]: the parameter type `Self` may not live long enough
+   |
+note: ...that is required by this bound
+  --> $DIR/supertrait-mentions-GAT.rs:6:15
+   |
+LL |         Self: 'a;
+   |               ^^
+   = help: consider adding an explicit lifetime bound `Self: 'a`...
+
+error: associated item referring to unboxed trait object for its own trait
+  --> $DIR/supertrait-mentions-GAT.rs:10:20
+   |
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+   |       ---------- in this trait
+LL |     fn c(&self) -> dyn SuperTrait<T>;
+   |                    ^^^^^^^^^^^^^^^^^
+   |
+help: you might have meant to use `Self` to refer to the implementing type
+   |
+LL |     fn c(&self) -> Self;
+   |                    ~~~~
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/supertrait-mentions-GAT.rs:10:20
+   |
+LL |     fn c(&self) -> dyn SuperTrait<T>;
+   |                    ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/supertrait-mentions-GAT.rs:4:10
+   |
+LL |     type Gat<'a>
+   |          ^^^ ...because it contains the generic associated type `Gat`
+...
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+   |       ---------- this trait cannot be made into an object...
+   = help: consider moving `Gat` to another trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0311.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-Self.rs b/tests/ui/dyn-compatibility/supertrait-mentions-Self.rs
new file mode 100644
index 00000000000..d96c7ba72a3
--- /dev/null
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.rs
@@ -0,0 +1,22 @@
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return position.
+
+trait Bar<T> {
+    fn bar(&self, x: &T);
+}
+
+trait Baz : Bar<Self> {
+    //~^ ERROR the size for values of type `Self` cannot be known
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> {
+    t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+    //~^ ERROR E0038
+    t
+}
+
+fn main() {
+}
diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr
new file mode 100644
index 00000000000..6474b115c46
--- /dev/null
+++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr
@@ -0,0 +1,42 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/supertrait-mentions-Self.rs:8:13
+   |
+LL | trait Baz : Bar<Self> {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+note: required by an implicit `Sized` bound in `Bar`
+  --> $DIR/supertrait-mentions-Self.rs:4:11
+   |
+LL | trait Bar<T> {
+   |           ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: consider further restricting `Self`
+   |
+LL | trait Baz : Bar<Self> + Sized {
+   |                       +++++++
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Bar<T: ?Sized> {
+   |            ++++++++
+
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/supertrait-mentions-Self.rs:16:31
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+   |                               ^^^^^^^ `Baz` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/supertrait-mentions-Self.rs:8:13
+   |
+LL | trait Baz : Bar<Self> {
+   |       ---   ^^^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider using an opaque type instead
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
+   |                               ~~~~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs
new file mode 100644
index 00000000000..5c71bd7769c
--- /dev/null
+++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs
@@ -0,0 +1,29 @@
+//@ compile-flags: --crate-type=lib
+// This test checks that the `where_clauses_object_safety` lint does not cause
+// other dyn-compatibility *hard errors* to be suppressed, because we currently
+// only emit one dyn-compatibility error per trait...
+// issue: rust-lang/rust#102762
+
+use std::future::Future;
+use std::pin::Pin;
+
+pub trait Fetcher: Send + Sync {
+    fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+    where
+        Self: Sync,
+    {
+        todo!()
+    }
+}
+
+fn fetcher() -> Box<dyn Fetcher> {
+    //~^ ERROR the trait `Fetcher` cannot be made into an object
+    todo!()
+}
+
+pub fn foo() {
+    let fetcher = fetcher();
+    //~^ ERROR the trait `Fetcher` cannot be made into an object
+    let _ = fetcher.get();
+    //~^ ERROR the trait `Fetcher` cannot be made into an object
+}
diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
new file mode 100644
index 00000000000..8d62ac9d923
--- /dev/null
+++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
@@ -0,0 +1,54 @@
+error[E0038]: the trait `Fetcher` cannot be made into an object
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21
+   |
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
+...
+LL | fn fetcher() -> Box<dyn Fetcher> {
+   |                     ^^^^^^^^^^^ `Fetcher` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
+   |
+LL | pub trait Fetcher: Send + Sync {
+   |           ------- this trait cannot be made into an object...
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
+
+error[E0038]: the trait `Fetcher` cannot be made into an object
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:25:19
+   |
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
+...
+LL |     let fetcher = fetcher();
+   |                   ^^^^^^^^^ `Fetcher` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
+   |
+LL | pub trait Fetcher: Send + Sync {
+   |           ------- this trait cannot be made into an object...
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
+
+error[E0038]: the trait `Fetcher` cannot be made into an object
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:27:13
+   |
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
+...
+LL |     let _ = fetcher.get();
+   |             ^^^^^^^^^^^^^ `Fetcher` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
+   |
+LL | pub trait Fetcher: Send + Sync {
+   |           ------- this trait cannot be made into an object...
+LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+   |                      ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.