about summary refs log tree commit diff
path: root/tests/ui/specialization
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/specialization
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/specialization')
-rw-r--r--tests/ui/specialization/README-rpass.md37
-rw-r--r--tests/ui/specialization/README.md21
-rw-r--r--tests/ui/specialization/assoc-ty-graph-cycle.rs25
-rw-r--r--tests/ui/specialization/assoc-ty-graph-cycle.stderr12
-rw-r--r--tests/ui/specialization/auxiliary/cross_crates_defaults.rs40
-rw-r--r--tests/ui/specialization/auxiliary/go_trait.rs43
-rw-r--r--tests/ui/specialization/auxiliary/specialization_cross_crate.rs72
-rw-r--r--tests/ui/specialization/const_trait_impl.rs55
-rw-r--r--tests/ui/specialization/cross-crate-defaults.rs41
-rw-r--r--tests/ui/specialization/cross-crate-defaults.stderr12
-rw-r--r--tests/ui/specialization/default-associated-type-bound-1.rs24
-rw-r--r--tests/ui/specialization/default-associated-type-bound-1.stderr26
-rw-r--r--tests/ui/specialization/default-associated-type-bound-2.rs22
-rw-r--r--tests/ui/specialization/default-associated-type-bound-2.stderr30
-rw-r--r--tests/ui/specialization/default-generic-associated-type-bound.rs25
-rw-r--r--tests/ui/specialization/default-generic-associated-type-bound.stderr30
-rw-r--r--tests/ui/specialization/defaultimpl/allowed-cross-crate.rs26
-rw-r--r--tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr12
-rw-r--r--tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs43
-rw-r--r--tests/ui/specialization/defaultimpl/out-of-order.rs19
-rw-r--r--tests/ui/specialization/defaultimpl/out-of-order.stderr12
-rw-r--r--tests/ui/specialization/defaultimpl/overlap-projection.rs25
-rw-r--r--tests/ui/specialization/defaultimpl/overlap-projection.stderr12
-rw-r--r--tests/ui/specialization/defaultimpl/projection.rs42
-rw-r--r--tests/ui/specialization/defaultimpl/projection.stderr12
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs11
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr14
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-no-default.rs77
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-no-default.stderr68
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs34
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr12
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs23
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr22
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs24
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr44
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-wfcheck.rs10
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr29
-rw-r--r--tests/ui/specialization/defaultimpl/validation.rs16
-rw-r--r--tests/ui/specialization/defaultimpl/validation.stderr51
-rw-r--r--tests/ui/specialization/issue-33017.rs45
-rw-r--r--tests/ui/specialization/issue-33017.stderr19
-rw-r--r--tests/ui/specialization/issue-35376.rs43
-rw-r--r--tests/ui/specialization/issue-35376.stderr12
-rw-r--r--tests/ui/specialization/issue-36804.rs35
-rw-r--r--tests/ui/specialization/issue-36804.stderr12
-rw-r--r--tests/ui/specialization/issue-38091-2.rs28
-rw-r--r--tests/ui/specialization/issue-38091-2.stderr21
-rw-r--r--tests/ui/specialization/issue-38091.rs24
-rw-r--r--tests/ui/specialization/issue-38091.stderr25
-rw-r--r--tests/ui/specialization/issue-39448.rs50
-rw-r--r--tests/ui/specialization/issue-39448.stderr30
-rw-r--r--tests/ui/specialization/issue-39618.rs27
-rw-r--r--tests/ui/specialization/issue-39618.stderr12
-rw-r--r--tests/ui/specialization/issue-43037.current.stderr12
-rw-r--r--tests/ui/specialization/issue-43037.negative.stderr12
-rw-r--r--tests/ui/specialization/issue-43037.rs22
-rw-r--r--tests/ui/specialization/issue-44861.rs40
-rw-r--r--tests/ui/specialization/issue-44861.stderr15
-rw-r--r--tests/ui/specialization/issue-45814.current.stderr14
-rw-r--r--tests/ui/specialization/issue-45814.negative.stderr14
-rw-r--r--tests/ui/specialization/issue-45814.rs13
-rw-r--r--tests/ui/specialization/issue-50452-fail.rs21
-rw-r--r--tests/ui/specialization/issue-50452-fail.stderr24
-rw-r--r--tests/ui/specialization/issue-50452.rs19
-rw-r--r--tests/ui/specialization/issue-50452.stderr12
-rw-r--r--tests/ui/specialization/issue-51892.rs18
-rw-r--r--tests/ui/specialization/issue-51892.stderr10
-rw-r--r--tests/ui/specialization/issue-52050.rs32
-rw-r--r--tests/ui/specialization/issue-52050.stderr24
-rw-r--r--tests/ui/specialization/issue-59435.rs17
-rw-r--r--tests/ui/specialization/issue-59435.stderr19
-rw-r--r--tests/ui/specialization/issue-63716-parse-async.rs14
-rw-r--r--tests/ui/specialization/issue-63716-parse-async.stderr12
-rw-r--r--tests/ui/specialization/issue-68830-spurious-diagnostics.rs23
-rw-r--r--tests/ui/specialization/issue-68830-spurious-diagnostics.stderr9
-rw-r--r--tests/ui/specialization/issue-70442.rs23
-rw-r--r--tests/ui/specialization/issue-70442.stderr12
-rw-r--r--tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs6
-rw-r--r--tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs32
-rw-r--r--tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr14
-rw-r--r--tests/ui/specialization/min_specialization/impl-on-nonexisting.rs7
-rw-r--r--tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr9
-rw-r--r--tests/ui/specialization/min_specialization/impl_specialization_trait.rs16
-rw-r--r--tests/ui/specialization/min_specialization/impl_specialization_trait.stderr10
-rw-r--r--tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs30
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.rs26
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.stderr27
-rw-r--r--tests/ui/specialization/min_specialization/repeated_projection_type.rs24
-rw-r--r--tests/ui/specialization/min_specialization/repeated_projection_type.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/repeating_lifetimes.rs19
-rw-r--r--tests/ui/specialization/min_specialization/repeating_lifetimes.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/repeating_param.rs17
-rw-r--r--tests/ui/specialization/min_specialization/repeating_param.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/spec-iter.rs20
-rw-r--r--tests/ui/specialization/min_specialization/spec-marker-supertraits.rs29
-rw-r--r--tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/spec-reference.rs19
-rw-r--r--tests/ui/specialization/min_specialization/specialization_marker.rs17
-rw-r--r--tests/ui/specialization/min_specialization/specialization_marker.stderr15
-rw-r--r--tests/ui/specialization/min_specialization/specialization_super_trait.rs18
-rw-r--r--tests/ui/specialization/min_specialization/specialization_super_trait.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/specialization_trait.rs26
-rw-r--r--tests/ui/specialization/min_specialization/specialization_trait.stderr20
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_marker.rs24
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs27
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_static.rs18
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_static.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_trait.rs20
-rw-r--r--tests/ui/specialization/min_specialization/specialize_on_trait.stderr8
-rw-r--r--tests/ui/specialization/non-defaulted-item-fail.rs54
-rw-r--r--tests/ui/specialization/non-defaulted-item-fail.stderr79
-rw-r--r--tests/ui/specialization/soundness/partial_eq_range_inclusive.rs35
-rw-r--r--tests/ui/specialization/soundness/partial_ord_slice.rs42
-rw-r--r--tests/ui/specialization/specialization-allowed-cross-crate.rs26
-rw-r--r--tests/ui/specialization/specialization-allowed-cross-crate.stderr12
-rw-r--r--tests/ui/specialization/specialization-assoc-fns.rs29
-rw-r--r--tests/ui/specialization/specialization-assoc-fns.stderr12
-rw-r--r--tests/ui/specialization/specialization-basics.rs98
-rw-r--r--tests/ui/specialization/specialization-basics.stderr12
-rw-r--r--tests/ui/specialization/specialization-cross-crate-no-gate.rs21
-rw-r--r--tests/ui/specialization/specialization-cross-crate.rs50
-rw-r--r--tests/ui/specialization/specialization-cross-crate.stderr12
-rw-r--r--tests/ui/specialization/specialization-default-methods.rs87
-rw-r--r--tests/ui/specialization/specialization-default-methods.stderr12
-rw-r--r--tests/ui/specialization/specialization-default-projection.rs36
-rw-r--r--tests/ui/specialization/specialization-default-projection.stderr43
-rw-r--r--tests/ui/specialization/specialization-default-types.rs35
-rw-r--r--tests/ui/specialization/specialization-default-types.stderr39
-rw-r--r--tests/ui/specialization/specialization-feature-gate-default.rs13
-rw-r--r--tests/ui/specialization/specialization-feature-gate-default.stderr12
-rw-r--r--tests/ui/specialization/specialization-feature-gate-overlap.rs17
-rw-r--r--tests/ui/specialization/specialization-feature-gate-overlap.stderr12
-rw-r--r--tests/ui/specialization/specialization-no-default.rs77
-rw-r--r--tests/ui/specialization/specialization-no-default.stderr68
-rw-r--r--tests/ui/specialization/specialization-on-projection.rs24
-rw-r--r--tests/ui/specialization/specialization-on-projection.stderr12
-rw-r--r--tests/ui/specialization/specialization-out-of-order.rs19
-rw-r--r--tests/ui/specialization/specialization-out-of-order.stderr12
-rw-r--r--tests/ui/specialization/specialization-overlap-hygiene.rs23
-rw-r--r--tests/ui/specialization/specialization-overlap-hygiene.stderr12
-rw-r--r--tests/ui/specialization/specialization-overlap-negative.rs11
-rw-r--r--tests/ui/specialization/specialization-overlap-negative.stderr21
-rw-r--r--tests/ui/specialization/specialization-overlap-projection.rs25
-rw-r--r--tests/ui/specialization/specialization-overlap-projection.stderr12
-rw-r--r--tests/ui/specialization/specialization-overlap.rs19
-rw-r--r--tests/ui/specialization/specialization-overlap.stderr45
-rw-r--r--tests/ui/specialization/specialization-polarity.rs17
-rw-r--r--tests/ui/specialization/specialization-polarity.stderr29
-rw-r--r--tests/ui/specialization/specialization-projection-alias.rs26
-rw-r--r--tests/ui/specialization/specialization-projection-alias.stderr12
-rw-r--r--tests/ui/specialization/specialization-projection.rs42
-rw-r--r--tests/ui/specialization/specialization-projection.stderr12
-rw-r--r--tests/ui/specialization/specialization-supertraits.rs17
-rw-r--r--tests/ui/specialization/specialization-supertraits.stderr12
-rw-r--r--tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs33
-rw-r--r--tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr12
-rw-r--r--tests/ui/specialization/specialization-translate-projections-with-params.rs32
-rw-r--r--tests/ui/specialization/specialization-translate-projections-with-params.stderr12
-rw-r--r--tests/ui/specialization/specialization-translate-projections.rs33
-rw-r--r--tests/ui/specialization/specialization-translate-projections.stderr12
-rw-r--r--tests/ui/specialization/transmute-specialization.rs15
-rw-r--r--tests/ui/specialization/transmute-specialization.stderr12
162 files changed, 4009 insertions, 0 deletions
diff --git a/tests/ui/specialization/README-rpass.md b/tests/ui/specialization/README-rpass.md
new file mode 100644
index 00000000000..c1486ce1ee8
--- /dev/null
+++ b/tests/ui/specialization/README-rpass.md
@@ -0,0 +1,37 @@
+Tests that specialization is working correctly:
+
+- Dispatch
+  - [On methods](specialization-basics.rs), includes:
+    - Specialization via adding a trait bound
+      - Including both remote and local traits
+    - Specialization via pure structure (e.g. `(T, U)` vs `(T, T)`)
+    - Specialization via concrete types vs unknown types
+      - In top level of the trait reference
+      - Embedded within another type (`Vec<T>` vs `Vec<i32>`)
+  - [Specialization based on super trait relationships](specialization-supertraits.rs)
+  - [On assoc fns](specialization-assoc-fns.rs)
+  - [Ensure that impl order doesn't matter](specialization-out-of-order.rs)
+
+- Item inheritance
+  - [Correct default cascading for methods](specialization-default-methods.rs)
+  - Inheritance works across impls with varying generics
+    - [With projections](specialization-translate-projections.rs)
+    - [With projections that involve input types](specialization-translate-projections-with-params.rs)
+
+- Normalization issues
+  - [Non-default assoc types can be projected](specialization-projection.rs)
+    - Including non-specialized cases
+    - Including specialized cases
+  - [Specialized Impls can happen on projections](specialization-on-projection.rs)
+  - [Projections and aliases play well together](specialization-projection-alias.rs)
+  - [Projections involving specialization allowed in the trait ref for impls, and overlap can still be determined](specialization-overlap-projection.rs)
+    - Only works for the simple case where the most specialized impl directly
+      provides a non-`default` associated type
+
+- Across crates
+  - [For traits defined in upstream crate](specialization-allowed-cross-crate.rs)
+  - [Full method dispatch tests, drawing from upstream crate](specialization-cross-crate.rs)
+    - Including *additional* local specializations
+  - [Full method dispatch tests, *without* turning on specialization in local crate](specialization-cross-crate-no-gate.rs)
+  - [Test that defaults cascade correctly from upstream crates](specialization-cross-crate-defaults.rs)
+    - Including *additional* local use of defaults
diff --git a/tests/ui/specialization/README.md b/tests/ui/specialization/README.md
new file mode 100644
index 00000000000..f2b4bf946c5
--- /dev/null
+++ b/tests/ui/specialization/README.md
@@ -0,0 +1,21 @@
+This directory contains the test for incorrect usage of specialization that
+should lead to compile failure. Those tests break down into a few categories:
+
+- Feature gating
+  - [On use of the `default` keyword](specialization-feature-gate-default.rs)
+  - [On overlapping impls](specialization-feature-gate-overlap.rs)
+
+- Overlap checking with specialization enabled
+  - [Basic overlap scenarios](specialization-overlap.rs)
+    - Includes purely structural overlap
+    - Includes purely trait-based overlap
+    - Includes mix
+  - [Overlap with differing polarity](specialization-overlap-negative.rs)
+
+- [Attempt to specialize without using `default`](specialization-no-default.rs)
+
+- [Attempt to change impl polarity in a specialization](specialization-polarity.rs)
+
+- Attempt to rely on projection of a `default` type
+  - [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs)
+  - [Rely on it both within an impl and outside it](specialization-default-types.rs)
diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs
new file mode 100644
index 00000000000..fc39b553a61
--- /dev/null
+++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+// Make sure we don't crash with a cycle error during coherence.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Trait<T> {
+    type Assoc;
+}
+
+impl<T> Trait<T> for Vec<T> {
+    default type Assoc = ();
+}
+
+impl Trait<u8> for Vec<u8> {
+    type Assoc = u8;
+}
+
+impl<T> Trait<T> for String {
+    type Assoc = ();
+}
+
+impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}
+
+fn main() {}
diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.stderr b/tests/ui/specialization/assoc-ty-graph-cycle.stderr
new file mode 100644
index 00000000000..f5529c24d3e
--- /dev/null
+++ b/tests/ui/specialization/assoc-ty-graph-cycle.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/assoc-ty-graph-cycle.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/auxiliary/cross_crates_defaults.rs b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs
new file mode 100644
index 00000000000..1e5555355c3
--- /dev/null
+++ b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs
@@ -0,0 +1,40 @@
+#![feature(specialization)]
+
+// First, test only use of explicit `default` items:
+
+pub trait Foo {
+    fn foo(&self) -> bool;
+}
+
+impl<T> Foo for T {
+    default fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+    fn foo(&self) -> bool { true }
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+pub trait Bar {
+    fn bar(&self) -> i32 { 0 }
+}
+
+impl<T> Bar for T {
+    default fn bar(&self) -> i32 { 0 }
+}
+
+impl Bar for i32 {
+    fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+impl<T> Bar for Vec<T> {
+    default fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+    fn bar(&self) -> i32 { 3 }
+}
diff --git a/tests/ui/specialization/auxiliary/go_trait.rs b/tests/ui/specialization/auxiliary/go_trait.rs
new file mode 100644
index 00000000000..aa0ec22896d
--- /dev/null
+++ b/tests/ui/specialization/auxiliary/go_trait.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+    fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+    this.go(arg)
+}
+
+pub trait GoMut {
+    fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+    this.go_mut(arg)
+}
+
+pub trait GoOnce {
+    fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+    this.go_once(arg)
+}
+
+impl<G> GoMut for G
+    where G : Go
+{
+    default fn go_mut(&mut self, arg: isize) {
+        go(&*self, arg)
+    }
+}
+
+impl<G> GoOnce for G
+    where G : GoMut
+{
+    default fn go_once(mut self, arg: isize) {
+        go_mut(&mut self, arg)
+    }
+}
diff --git a/tests/ui/specialization/auxiliary/specialization_cross_crate.rs b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs
new file mode 100644
index 00000000000..8caa8524fb9
--- /dev/null
+++ b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs
@@ -0,0 +1,72 @@
+#![feature(specialization)]
+
+pub trait Foo {
+    fn foo(&self) -> &'static str;
+}
+
+impl<T> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic"
+    }
+}
+
+impl<T: Clone> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic Clone"
+    }
+}
+
+impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+    default fn foo(&self) -> &'static str {
+        "generic pair"
+    }
+}
+
+impl<T: Clone> Foo for (T, T) {
+    default fn foo(&self) -> &'static str {
+        "generic uniform pair"
+    }
+}
+
+impl Foo for (u8, u32) {
+    default fn foo(&self) -> &'static str {
+        "(u8, u32)"
+    }
+}
+
+impl Foo for (u8, u8) {
+    default fn foo(&self) -> &'static str {
+        "(u8, u8)"
+    }
+}
+
+impl<T: Clone> Foo for Vec<T> {
+    default fn foo(&self) -> &'static str {
+        "generic Vec"
+    }
+}
+
+impl Foo for Vec<i32> {
+    fn foo(&self) -> &'static str {
+        "Vec<i32>"
+    }
+}
+
+impl Foo for String {
+    fn foo(&self) -> &'static str {
+        "String"
+    }
+}
+
+impl Foo for i32 {
+    fn foo(&self) -> &'static str {
+        "i32"
+    }
+}
+
+pub trait MyMarker {}
+impl<T: Clone + MyMarker> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic Clone + MyMarker"
+    }
+}
diff --git a/tests/ui/specialization/const_trait_impl.rs b/tests/ui/specialization/const_trait_impl.rs
new file mode 100644
index 00000000000..05ba4c8d45d
--- /dev/null
+++ b/tests/ui/specialization/const_trait_impl.rs
@@ -0,0 +1,55 @@
+// check-pass
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub unsafe trait Sup {
+    fn foo() -> u32;
+}
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub unsafe trait Sub: ~const Sup {}
+
+unsafe impl const Sup for u8 {
+    default fn foo() -> u32 {
+        1
+    }
+}
+
+unsafe impl const Sup for () {
+    fn foo() -> u32 {
+        42
+    }
+}
+
+unsafe impl const Sub for () {}
+
+#[const_trait]
+pub trait A {
+    fn a() -> u32;
+}
+
+impl<T: ~const Default> const A for T {
+    default fn a() -> u32 {
+        2
+    }
+}
+
+impl<T: ~const Default + ~const Sup> const A for T {
+    default fn a() -> u32 {
+        3
+    }
+}
+
+impl<T: ~const Default + ~const Sub> const A for T {
+    fn a() -> u32 {
+        T::foo()
+    }
+}
+
+const _: () = assert!(<()>::a() == 42);
+const _: () = assert!(<u8>::a() == 3);
+const _: () = assert!(<u16>::a() == 2);
+
+fn main() {}
diff --git a/tests/ui/specialization/cross-crate-defaults.rs b/tests/ui/specialization/cross-crate-defaults.rs
new file mode 100644
index 00000000000..fc28d0c815e
--- /dev/null
+++ b/tests/ui/specialization/cross-crate-defaults.rs
@@ -0,0 +1,41 @@
+// run-pass
+
+// aux-build:cross_crates_defaults.rs
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+extern crate cross_crates_defaults;
+
+use cross_crates_defaults::*;
+
+struct LocalDefault;
+struct LocalOverride;
+
+impl Foo for LocalDefault {}
+
+impl Foo for LocalOverride {
+    fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+    assert!(!0i8.foo());
+    assert!(!0i32.foo());
+    assert!(0i64.foo());
+
+    assert!(!LocalDefault.foo());
+    assert!(LocalOverride.foo());
+}
+
+fn test_bar() {
+    assert!(0u8.bar() == 0);
+    assert!(0i32.bar() == 1);
+    assert!("hello".bar() == 0);
+    assert!(vec![()].bar() == 2);
+    assert!(vec![0i32].bar() == 2);
+    assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+    test_foo();
+    test_bar();
+}
diff --git a/tests/ui/specialization/cross-crate-defaults.stderr b/tests/ui/specialization/cross-crate-defaults.stderr
new file mode 100644
index 00000000000..ee5c77a76be
--- /dev/null
+++ b/tests/ui/specialization/cross-crate-defaults.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/cross-crate-defaults.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/default-associated-type-bound-1.rs b/tests/ui/specialization/default-associated-type-bound-1.rs
new file mode 100644
index 00000000000..c043114b565
--- /dev/null
+++ b/tests/ui/specialization/default-associated-type-bound-1.rs
@@ -0,0 +1,24 @@
+// Check that we check that default associated types satisfy the required
+// bounds on them.
+
+#![feature(specialization)]
+//~^ WARNING `specialization` is incomplete
+
+trait X {
+    type U: Clone;
+    fn unsafe_clone(&self, x: Option<&Self::U>) {
+        x.cloned();
+    }
+}
+
+// We cannot normalize `<T as X>::U` to `str` here, because the default could
+// be overridden. The error here must therefore be found by a method other than
+// normalization.
+impl<T> X for T {
+    default type U = str;
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
+
+pub fn main() {
+    1.unsafe_clone(None);
+}
diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr
new file mode 100644
index 00000000000..e498187c0a1
--- /dev/null
+++ b/tests/ui/specialization/default-associated-type-bound-1.stderr
@@ -0,0 +1,26 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-associated-type-bound-1.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `str: Clone` is not satisfied
+  --> $DIR/default-associated-type-bound-1.rs:18:22
+   |
+LL |     default type U = str;
+   |                      ^^^ the trait `Clone` is not implemented for `str`
+   |
+   = help: the trait `Clone` is implemented for `String`
+note: required by a bound in `X::U`
+  --> $DIR/default-associated-type-bound-1.rs:8:13
+   |
+LL |     type U: Clone;
+   |             ^^^^^ required by this bound in `X::U`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/default-associated-type-bound-2.rs b/tests/ui/specialization/default-associated-type-bound-2.rs
new file mode 100644
index 00000000000..0a21b1f0910
--- /dev/null
+++ b/tests/ui/specialization/default-associated-type-bound-2.rs
@@ -0,0 +1,22 @@
+// Check that generic predicates are also checked for default associated types.
+#![feature(specialization)]
+//~^ WARNING `specialization` is incomplete
+
+trait X<T> {
+    type U: PartialEq<T>;
+    fn unsafe_compare(x: Option<Self::U>, y: Option<T>) {
+        match (x, y) {
+            (Some(a), Some(b)) => a == b,
+            _ => false,
+        };
+    }
+}
+
+impl<B: 'static, T> X<B> for T {
+    default type U = &'static B;
+    //~^ ERROR can't compare `&'static B` with `B`
+}
+
+pub fn main() {
+    <i32 as X<i32>>::unsafe_compare(None, None);
+}
diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr
new file mode 100644
index 00000000000..4dbe251ed5e
--- /dev/null
+++ b/tests/ui/specialization/default-associated-type-bound-2.stderr
@@ -0,0 +1,30 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-associated-type-bound-2.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: can't compare `&'static B` with `B`
+  --> $DIR/default-associated-type-bound-2.rs:16:22
+   |
+LL |     default type U = &'static B;
+   |                      ^^^^^^^^^^ no implementation for `&'static B == B`
+   |
+   = help: the trait `PartialEq<B>` is not implemented for `&'static B`
+note: required by a bound in `X::U`
+  --> $DIR/default-associated-type-bound-2.rs:6:13
+   |
+LL |     type U: PartialEq<T>;
+   |             ^^^^^^^^^^^^ required by this bound in `X::U`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | impl<B: 'static, T> X<B> for T where &'static B: PartialEq<B> {
+   |                                ++++++++++++++++++++++++++++++
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/default-generic-associated-type-bound.rs b/tests/ui/specialization/default-generic-associated-type-bound.rs
new file mode 100644
index 00000000000..31a0685d004
--- /dev/null
+++ b/tests/ui/specialization/default-generic-associated-type-bound.rs
@@ -0,0 +1,25 @@
+// Check that default generics associated types are validated.
+
+#![feature(specialization)]
+//~^ WARNING `specialization` is incomplete
+
+trait X {
+    type U<'a>: PartialEq<&'a Self> where Self: 'a;
+    fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) {
+        match (x, y) {
+            (Some(a), Some(b)) => a == b,
+            _ => false,
+        };
+    }
+}
+
+impl<T: 'static> X for T {
+    default type U<'a> = &'a T;
+    //~^ ERROR can't compare `T` with `T`
+}
+
+struct NotComparable;
+
+pub fn main() {
+    <NotComparable as X>::unsafe_compare(None, None);
+}
diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr
new file mode 100644
index 00000000000..c597eed3790
--- /dev/null
+++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr
@@ -0,0 +1,30 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-generic-associated-type-bound.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: can't compare `T` with `T`
+  --> $DIR/default-generic-associated-type-bound.rs:17:26
+   |
+LL |     default type U<'a> = &'a T;
+   |                          ^^^^^ no implementation for `T == T`
+   |
+   = note: required for `&'a T` to implement `PartialEq`
+note: required by a bound in `X::U`
+  --> $DIR/default-generic-associated-type-bound.rs:7:17
+   |
+LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
+   |                 ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U`
+help: consider further restricting this bound
+   |
+LL | impl<T: 'static + std::cmp::PartialEq> X for T {
+   |                 +++++++++++++++++++++
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs
new file mode 100644
index 00000000000..5d67160eb96
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+
+// aux-build:go_trait.rs
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+extern crate go_trait;
+
+use go_trait::{Go,GoMut};
+use std::fmt::Debug;
+use std::default::Default;
+
+struct MyThingy;
+
+impl Go for MyThingy {
+    fn go(&self, arg: isize) { }
+}
+
+impl GoMut for MyThingy {
+    fn go_mut(&mut self, arg: isize) { }
+}
+
+fn main() { }
diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr
new file mode 100644
index 00000000000..02f13d461c3
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs
new file mode 100644
index 00000000000..c065593b432
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs
@@ -0,0 +1,43 @@
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+    fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+    this.go(arg)
+}
+
+pub trait GoMut {
+    fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+    this.go_mut(arg)
+}
+
+pub trait GoOnce {
+    fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+    this.go_once(arg)
+}
+
+default impl<G> GoMut for G
+    where G : Go
+{
+    fn go_mut(&mut self, arg: isize) {
+        go(&*self, arg)
+    }
+}
+
+default impl<G> GoOnce for G
+    where G : GoMut
+{
+    fn go_once(mut self, arg: isize) {
+        go_mut(&mut self, arg)
+    }
+}
diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs
new file mode 100644
index 00000000000..13258ac8c9f
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/out-of-order.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+// Test that you can list the more specific impl before the more general one.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    type Out;
+}
+
+impl Foo for bool {
+    type Out = ();
+}
+
+default impl<T> Foo for T {
+    type Out = bool;
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/out-of-order.stderr b/tests/ui/specialization/defaultimpl/out-of-order.stderr
new file mode 100644
index 00000000000..2cf1ac90959
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/out-of-order.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs
new file mode 100644
index 00000000000..0add4d5516c
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+// Test that impls on projected self types can resolve overlap, even when the
+// projections involve specialization, so long as the associated type is
+// provided by the most specialized impl.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Assoc {
+    type Output;
+}
+
+default impl<T> Assoc for T {
+    type Output = bool;
+}
+
+impl Assoc for u8 { type Output = u8; }
+impl Assoc for u16 { type Output = u16; }
+
+trait Foo {}
+impl Foo for u32 {}
+impl Foo for <u8 as Assoc>::Output {}
+impl Foo for <u16 as Assoc>::Output {}
+
+fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.stderr b/tests/ui/specialization/defaultimpl/overlap-projection.stderr
new file mode 100644
index 00000000000..75fdfafd9d1
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/overlap-projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/defaultimpl/projection.rs b/tests/ui/specialization/defaultimpl/projection.rs
new file mode 100644
index 00000000000..f19c55b043b
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/projection.rs
@@ -0,0 +1,42 @@
+// run-pass
+#![allow(dead_code)]
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Make sure we *can* project non-defaulted associated types
+// cf ui/specialization/specialization-default-projection.rs
+
+// First, do so without any use of specialization
+
+trait Foo {
+    type Assoc;
+}
+
+impl<T> Foo for T {
+    type Assoc = ();
+}
+
+fn generic_foo<T>() -> <T as Foo>::Assoc {
+    ()
+}
+
+// Next, allow for one layer of specialization
+
+trait Bar {
+    type Assoc;
+}
+
+default impl<T> Bar for T {
+    type Assoc = ();
+}
+
+impl<T: Clone> Bar for T {
+    type Assoc = u8;
+}
+
+fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc {
+    0u8
+}
+
+fn main() {
+}
diff --git a/tests/ui/specialization/defaultimpl/projection.stderr b/tests/ui/specialization/defaultimpl/projection.stderr
new file mode 100644
index 00000000000..cc3fe8237a7
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs
new file mode 100644
index 00000000000..89158b65a6e
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs
@@ -0,0 +1,11 @@
+// Check that specialization must be ungated to use the `default` keyword
+
+trait Foo {
+    fn foo(&self);
+}
+
+default impl<T> Foo for T { //~ ERROR specialization is unstable
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
new file mode 100644
index 00000000000..64e14f5800f
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
@@ -0,0 +1,14 @@
+error[E0658]: specialization is unstable
+  --> $DIR/specialization-feature-gate-default.rs:7:1
+   |
+LL | / default impl<T> Foo for T {
+LL | |     fn foo(&self) {}
+LL | | }
+   | |_^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: add `#![feature(specialization)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
new file mode 100644
index 00000000000..661724eef8a
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -0,0 +1,77 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+// Test 1: one layer of specialization, multiple methods, missing `default`
+
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+    fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+    fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+    fn bar(&self) {} //~ ERROR E0520
+}
+
+// Test 2: one layer of specialization, missing `default` on associated type
+
+trait Bar {
+    type T;
+}
+
+impl<T> Bar for T {
+    type T = u8;
+}
+
+impl Bar for u8 {
+    type T = (); //~ ERROR E0520
+}
+
+// Test 3a: multiple layers of specialization, missing interior `default`
+
+trait Baz {
+    fn baz(&self);
+}
+
+default impl<T> Baz for T {
+    fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+    fn baz(&self) {}
+}
+
+impl Baz for i32 {
+    fn baz(&self) {} //~ ERROR E0520
+}
+
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+
+trait Redundant {
+    fn redundant(&self);
+}
+
+default impl<T> Redundant for T {
+    fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+    fn redundant(&self) {}
+}
+
+default impl Redundant for i32 {
+    fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
new file mode 100644
index 00000000000..770be2af281
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -0,0 +1,68 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:20:5
+   |
+LL | impl<T> Foo for T {
+   | ----------------- parent `impl` is here
+...
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:23:5
+   |
+LL | impl<T> Foo for T {
+   | ----------------- parent `impl` is here
+...
+LL |     fn bar(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |
+   = note: to specialize, `bar` in the parent `impl` must be marked `default`
+
+error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:37:5
+   |
+LL | impl<T> Bar for T {
+   | ----------------- parent `impl` is here
+...
+LL |     type T = ();
+   |     ^^^^^^^^^^^^ cannot specialize default item `T`
+   |
+   = note: to specialize, `T` in the parent `impl` must be marked `default`
+
+error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:55:5
+   |
+LL | impl<T: Clone> Baz for T {
+   | ------------------------ parent `impl` is here
+...
+LL |     fn baz(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |
+   = note: to specialize, `baz` in the parent `impl` must be marked `default`
+
+error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:74:5
+   |
+LL | impl<T: Clone> Redundant for T {
+   | ------------------------------ parent `impl` is here
+...
+LL |     fn redundant(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |
+   = note: to specialize, `redundant` in the parent `impl` must be marked `default`
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
new file mode 100644
index 00000000000..89fef5b5ef9
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
@@ -0,0 +1,34 @@
+// run-pass
+
+// Tests that we can combine a default impl that supplies one method with a
+// full impl that supplies the other, and they can invoke one another.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    fn foo_one(&self) -> &'static str;
+    fn foo_two(&self) -> &'static str;
+    fn foo_three(&self) -> &'static str;
+}
+
+struct MyStruct;
+
+default impl<T> Foo for T {
+    fn foo_one(&self) -> &'static str {
+        self.foo_three()
+    }
+}
+
+impl Foo for MyStruct {
+    fn foo_two(&self) -> &'static str {
+        self.foo_one()
+    }
+
+    fn foo_three(&self) -> &'static str {
+        "generic"
+    }
+}
+
+fn main() {
+    assert!(MyStruct.foo_two() == "generic");
+}
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
new file mode 100644
index 00000000000..407c1ab7720
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
new file mode 100644
index 00000000000..3c5414469fa
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
@@ -0,0 +1,23 @@
+// Tests that default impls do not have to supply all items but regular impls do.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    fn foo_one(&self) -> &'static str;
+    fn foo_two(&self) -> &'static str;
+}
+
+struct MyStruct;
+
+default impl<T> Foo for T {
+    fn foo_one(&self) -> &'static str {
+        "generic"
+    }
+}
+
+impl Foo for MyStruct {}
+//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046]
+
+fn main() {
+    println!("{}", MyStruct.foo_one());
+}
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
new file mode 100644
index 00000000000..f19975060a4
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -0,0 +1,22 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0046]: not all trait items implemented, missing: `foo_two`
+  --> $DIR/specialization-trait-item-not-implemented.rs:18:1
+   |
+LL |     fn foo_two(&self) -> &'static str;
+   |     ---------------------------------- `foo_two` from trait
+...
+LL | impl Foo for MyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
new file mode 100644
index 00000000000..6834d573629
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -0,0 +1,24 @@
+// Tests that:
+// - default impls do not have to supply all items and
+// - a default impl does not count as an impl (in this case, an incomplete default impl).
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    fn foo_one(&self) -> &'static str;
+    fn foo_two(&self) -> &'static str;
+}
+
+struct MyStruct;
+
+default impl<T> Foo for T {
+    fn foo_one(&self) -> &'static str {
+        "generic"
+    }
+}
+
+
+fn main() {
+    println!("{}", MyStruct.foo_one());
+    //~^ ERROR the method
+}
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
new file mode 100644
index 00000000000..37788612f43
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -0,0 +1,44 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-not-implemented.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied
+  --> $DIR/specialization-trait-not-implemented.rs:22:29
+   |
+LL | struct MyStruct;
+   | ---------------
+   | |
+   | method `foo_one` not found for this struct
+   | doesn't satisfy `MyStruct: Foo`
+...
+LL |     println!("{}", MyStruct.foo_one());
+   |                             ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds
+   |
+note: trait bound `MyStruct: Foo` was not satisfied
+  --> $DIR/specialization-trait-not-implemented.rs:14:1
+   |
+LL | default impl<T> Foo for T {
+   | ^^^^^^^^^^^^^^^^---^^^^^-
+   | |
+   | unsatisfied trait bound introduced here
+note: the trait `Foo` must be implemented
+  --> $DIR/specialization-trait-not-implemented.rs:7:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `Foo` defines an item `foo_one`, perhaps you need to implement it
+  --> $DIR/specialization-trait-not-implemented.rs:7:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs
new file mode 100644
index 00000000000..eb18d6eaac4
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs
@@ -0,0 +1,10 @@
+// Tests that a default impl still has to have a WF trait ref.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo<'a, T: Eq + 'a> { }
+
+default impl<U> Foo<'static, U> for () {}
+//~^ ERROR the trait bound `U: Eq` is not satisfied
+
+fn main(){}
diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
new file mode 100644
index 00000000000..e7801603493
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -0,0 +1,29 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-wfcheck.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `U: Eq` is not satisfied
+  --> $DIR/specialization-wfcheck.rs:7:17
+   |
+LL | default impl<U> Foo<'static, U> for () {}
+   |                 ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `U`
+   |
+note: required by a bound in `Foo`
+  --> $DIR/specialization-wfcheck.rs:5:18
+   |
+LL | trait Foo<'a, T: Eq + 'a> { }
+   |                  ^^ required by this bound in `Foo`
+help: consider restricting type parameter `U`
+   |
+LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {}
+   |               ++++++++++++++
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs
new file mode 100644
index 00000000000..8558a1efb82
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/validation.rs
@@ -0,0 +1,16 @@
+#![feature(negative_impls)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+struct S;
+struct Z;
+
+default impl S {} //~ ERROR inherent impls cannot be `default`
+
+default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
+default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
+                            //~^ ERROR negative impls cannot be default impls
+
+trait Tr {}
+default impl !Tr for S {} //~ ERROR negative impls cannot be default impls
+
+fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr
new file mode 100644
index 00000000000..eb6dc9355a3
--- /dev/null
+++ b/tests/ui/specialization/defaultimpl/validation.stderr
@@ -0,0 +1,51 @@
+error: inherent impls cannot be `default`
+  --> $DIR/validation.rs:7:14
+   |
+LL | default impl S {}
+   | -------      ^ inherent impl for this type
+   | |
+   | `default` because of this
+   |
+   = note: only trait implementations may be annotated with `default`
+
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/validation.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: impls of auto traits cannot be default
+  --> $DIR/validation.rs:9:21
+   |
+LL | default unsafe impl Send for S {}
+   | -------             ^^^^ auto trait
+   | |
+   | default because of this
+
+error: impls of auto traits cannot be default
+  --> $DIR/validation.rs:10:15
+   |
+LL | default impl !Send for Z {}
+   | -------       ^^^^ auto trait
+   | |
+   | default because of this
+
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/validation.rs:10:1
+   |
+LL | default impl !Send for Z {}
+   | ^^^^^^^      ^
+
+error[E0750]: negative impls cannot be default impls
+  --> $DIR/validation.rs:14:1
+   |
+LL | default impl !Tr for S {}
+   | ^^^^^^^      ^
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0750`.
diff --git a/tests/ui/specialization/issue-33017.rs b/tests/ui/specialization/issue-33017.rs
new file mode 100644
index 00000000000..8dbadf58d5c
--- /dev/null
+++ b/tests/ui/specialization/issue-33017.rs
@@ -0,0 +1,45 @@
+// Test to ensure that trait bounds are properly
+// checked on specializable associated types
+
+#![allow(incomplete_features)]
+#![feature(specialization)]
+
+trait UncheckedCopy: Sized {
+    type Output: From<Self> + Copy + Into<Self>;
+}
+
+impl<T> UncheckedCopy for T {
+    default type Output = Self;
+    //~^ ERROR: the trait bound `T: Copy` is not satisfied
+}
+
+fn unchecked_copy<T: UncheckedCopy>(other: &T::Output) -> T {
+    (*other).into()
+}
+
+fn bug(origin: String) {
+    // Turn the String into it's Output type...
+    // Which we can just do by `.into()`, the assoc type states `From<Self>`.
+    let origin_output = origin.into();
+
+    // Make a copy of String::Output, which is a String...
+    let mut copy: String = unchecked_copy::<String>(&origin_output);
+
+    // Turn the Output type into a String again,
+    // Which we can just do by `.into()`, the assoc type states `Into<Self>`.
+    let mut origin: String = origin_output.into();
+
+    // assert both Strings use the same buffer.
+    assert_eq!(copy.as_ptr(), origin.as_ptr());
+
+    // Any use of the copy we made becomes invalid,
+    drop(origin);
+
+    // OH NO! UB UB UB UB!
+    copy.push_str(" world!");
+    println!("{}", copy);
+}
+
+fn main() {
+    bug(String::from("hello"));
+}
diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr
new file mode 100644
index 00000000000..78e94cec2c0
--- /dev/null
+++ b/tests/ui/specialization/issue-33017.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/issue-33017.rs:12:27
+   |
+LL |     default type Output = Self;
+   |                           ^^^^ the trait `Copy` is not implemented for `T`
+   |
+note: required by a bound in `UncheckedCopy::Output`
+  --> $DIR/issue-33017.rs:8:31
+   |
+LL |     type Output: From<Self> + Copy + Into<Self>;
+   |                               ^^^^ required by this bound in `UncheckedCopy::Output`
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::marker::Copy> UncheckedCopy for T {
+   |       +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/issue-35376.rs b/tests/ui/specialization/issue-35376.rs
new file mode 100644
index 00000000000..cc35213b93d
--- /dev/null
+++ b/tests/ui/specialization/issue-35376.rs
@@ -0,0 +1,43 @@
+// check-pass
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+fn main() {}
+
+pub trait Alpha<T> { }
+
+pub trait Beta {
+    type Event;
+}
+
+pub trait Delta {
+    type Handle;
+    fn process(&self);
+}
+
+pub struct Parent<A, T>(A, T);
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+    type Handle = Handle;
+    default fn process(&self) {
+        unimplemented!()
+    }
+}
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle> + Alpha<Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+      fn process(&self) {
+        unimplemented!()
+      }
+}
+
+pub struct Handle;
+
+impl Beta for Handle {
+    type Event = ();
+}
diff --git a/tests/ui/specialization/issue-35376.stderr b/tests/ui/specialization/issue-35376.stderr
new file mode 100644
index 00000000000..6c4167f3f9f
--- /dev/null
+++ b/tests/ui/specialization/issue-35376.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-35376.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/issue-36804.rs b/tests/ui/specialization/issue-36804.rs
new file mode 100644
index 00000000000..89350602f36
--- /dev/null
+++ b/tests/ui/specialization/issue-36804.rs
@@ -0,0 +1,35 @@
+// check-pass
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+pub struct Cloned<I>(I);
+
+impl<'a, I, T: 'a> Iterator for Cloned<I>
+where
+    I: Iterator<Item = &'a T>,
+    T: Clone,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        unimplemented!()
+    }
+
+    default fn count(self) -> usize where Self: Sized {
+        self.fold(0, |cnt, _| cnt + 1)
+    }
+}
+
+impl<'a, I, T: 'a> Iterator for Cloned<I>
+where
+    I: Iterator<Item = &'a T>,
+    T: Copy,
+{
+    fn count(self) -> usize {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    let a = [1,2,3,4];
+    Cloned(a.iter()).count();
+}
diff --git a/tests/ui/specialization/issue-36804.stderr b/tests/ui/specialization/issue-36804.stderr
new file mode 100644
index 00000000000..c2113b25f19
--- /dev/null
+++ b/tests/ui/specialization/issue-36804.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-36804.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/issue-38091-2.rs b/tests/ui/specialization/issue-38091-2.rs
new file mode 100644
index 00000000000..9ed0b240d0a
--- /dev/null
+++ b/tests/ui/specialization/issue-38091-2.rs
@@ -0,0 +1,28 @@
+// build-fail
+//~^ ERROR overflow evaluating the requirement `i32: Check`
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+    type Ty: Valid;
+    fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+    T: Check,
+{
+    default type Ty = ();
+    default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+impl Valid for () {}
+
+fn main() {
+    Iterate::iterate(0);
+}
diff --git a/tests/ui/specialization/issue-38091-2.stderr b/tests/ui/specialization/issue-38091-2.stderr
new file mode 100644
index 00000000000..117fb10bb7e
--- /dev/null
+++ b/tests/ui/specialization/issue-38091-2.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091-2.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0275]: overflow evaluating the requirement `i32: Check`
+   |
+note: required for `i32` to implement `Iterate<'_>`
+  --> $DIR/issue-38091-2.rs:11:13
+   |
+LL | impl<'a, T> Iterate<'a> for T
+   |             ^^^^^^^^^^^     ^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/specialization/issue-38091.rs b/tests/ui/specialization/issue-38091.rs
new file mode 100644
index 00000000000..5b398368a67
--- /dev/null
+++ b/tests/ui/specialization/issue-38091.rs
@@ -0,0 +1,24 @@
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+    type Ty: Valid;
+    fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+    T: Check,
+{
+    default type Ty = ();
+    //~^ ERROR the trait bound `(): Valid` is not satisfied
+    default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+    Iterate::iterate(0);
+}
diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr
new file mode 100644
index 00000000000..f2210a40719
--- /dev/null
+++ b/tests/ui/specialization/issue-38091.stderr
@@ -0,0 +1,25 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `(): Valid` is not satisfied
+  --> $DIR/issue-38091.rs:12:23
+   |
+LL |     default type Ty = ();
+   |                       ^^ the trait `Valid` is not implemented for `()`
+   |
+note: required by a bound in `Iterate::Ty`
+  --> $DIR/issue-38091.rs:5:14
+   |
+LL |     type Ty: Valid;
+   |              ^^^^^ required by this bound in `Iterate::Ty`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/issue-39448.rs b/tests/ui/specialization/issue-39448.rs
new file mode 100644
index 00000000000..a15c4bd6b7f
--- /dev/null
+++ b/tests/ui/specialization/issue-39448.rs
@@ -0,0 +1,50 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Regression test for a specialization-related ICE (#39448).
+
+trait A: Sized {
+    fn foo(self, _: Self) -> Self {
+        self
+    }
+}
+
+impl A for u8 {}
+impl A for u16 {}
+
+impl FromA<u8> for u16 {
+    fn from(x: u8) -> u16 {
+        x as u16
+    }
+}
+
+trait FromA<T> {
+    fn from(t: T) -> Self;
+}
+
+impl<T: A, U: A + FromA<T>> FromA<T> for U {
+    default fn from(x: T) -> Self {
+        ToA::to(x)
+    }
+}
+
+trait ToA<T> {
+    fn to(self) -> T;
+}
+
+impl<T, U> ToA<U> for T
+where
+    U: FromA<T>,
+{
+    fn to(self) -> U {
+        U::from(self)
+    }
+}
+
+#[allow(dead_code)]
+fn foo<T: A, U: A>(x: T, y: U) -> U {
+    x.foo(y.to()).to() //~ ERROR overflow evaluating the requirement
+}
+
+fn main() {
+    let z = foo(8u8, 1u16);
+}
diff --git a/tests/ui/specialization/issue-39448.stderr b/tests/ui/specialization/issue-39448.stderr
new file mode 100644
index 00000000000..60157d9a3e1
--- /dev/null
+++ b/tests/ui/specialization/issue-39448.stderr
@@ -0,0 +1,30 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39448.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0275]: overflow evaluating the requirement `T: FromA<U>`
+  --> $DIR/issue-39448.rs:45:13
+   |
+LL |     x.foo(y.to()).to()
+   |             ^^
+   |
+note: required for `T` to implement `FromA<U>`
+  --> $DIR/issue-39448.rs:24:29
+   |
+LL | impl<T: A, U: A + FromA<T>> FromA<T> for U {
+   |                             ^^^^^^^^     ^
+note: required for `U` to implement `ToA<T>`
+  --> $DIR/issue-39448.rs:34:12
+   |
+LL | impl<T, U> ToA<U> for T
+   |            ^^^^^^     ^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/specialization/issue-39618.rs b/tests/ui/specialization/issue-39618.rs
new file mode 100644
index 00000000000..72630ee9c70
--- /dev/null
+++ b/tests/ui/specialization/issue-39618.rs
@@ -0,0 +1,27 @@
+// Regression test for #39618, shouldn't crash.
+// FIXME(JohnTitor): Centril pointed out this looks suspicions, we should revisit here.
+// More context: https://github.com/rust-lang/rust/pull/69192#discussion_r379846796
+
+// check-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    fn foo(&self);
+}
+
+trait Bar {
+    fn bar(&self);
+}
+
+impl<T> Bar for T where T: Foo {
+    fn bar(&self) {}
+}
+
+impl<T> Foo for T where T: Bar {
+    fn foo(&self) {}
+}
+
+impl Foo for u64 {}
+
+fn main() {}
diff --git a/tests/ui/specialization/issue-39618.stderr b/tests/ui/specialization/issue-39618.stderr
new file mode 100644
index 00000000000..19de60c7c17
--- /dev/null
+++ b/tests/ui/specialization/issue-39618.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39618.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/issue-43037.current.stderr b/tests/ui/specialization/issue-43037.current.stderr
new file mode 100644
index 00000000000..26db9d7c997
--- /dev/null
+++ b/tests/ui/specialization/issue-43037.current.stderr
@@ -0,0 +1,12 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/issue-43037.rs:19:6
+   |
+LL | impl<T> From<<A<T> as Z>::Assoc> for T {}
+   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/specialization/issue-43037.negative.stderr b/tests/ui/specialization/issue-43037.negative.stderr
new file mode 100644
index 00000000000..26db9d7c997
--- /dev/null
+++ b/tests/ui/specialization/issue-43037.negative.stderr
@@ -0,0 +1,12 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/issue-43037.rs:19:6
+   |
+LL | impl<T> From<<A<T> as Z>::Assoc> for T {}
+   |      ^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/specialization/issue-43037.rs b/tests/ui/specialization/issue-43037.rs
new file mode 100644
index 00000000000..a1e3f998b23
--- /dev/null
+++ b/tests/ui/specialization/issue-43037.rs
@@ -0,0 +1,22 @@
+// revisions: current negative
+#![feature(specialization)]
+#![cfg_attr(negative, feature(with_negative_coherence))]
+#![allow(incomplete_features)]
+
+trait X {}
+trait Y: X {}
+trait Z {
+    type Assoc: Y;
+}
+struct A<T>(T);
+
+impl<T> Y for T where T: X {}
+impl<T: X> Z for A<T> {
+    type Assoc = T;
+}
+
+// this impl is invalid, but causes an ICE anyway
+impl<T> From<<A<T> as Z>::Assoc> for T {}
+//~^ ERROR type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+
+fn main() {}
diff --git a/tests/ui/specialization/issue-44861.rs b/tests/ui/specialization/issue-44861.rs
new file mode 100644
index 00000000000..79d9b9490d0
--- /dev/null
+++ b/tests/ui/specialization/issue-44861.rs
@@ -0,0 +1,40 @@
+#![crate_type = "lib"]
+#![feature(specialization)]
+#![feature(unsize, coerce_unsized)]
+#![allow(incomplete_features)]
+
+use std::ops::CoerceUnsized;
+
+pub struct SmartassPtr<A: Smartass+?Sized>(A::Data);
+
+pub trait Smartass {
+    type Data;
+    type Data2: CoerceUnsized<*const [u8]>;
+}
+
+pub trait MaybeObjectSafe {}
+
+impl MaybeObjectSafe for () {}
+
+impl<T> Smartass for T {
+    type Data = <Self as Smartass>::Data2;
+    default type Data2 = ();
+    //~^ ERROR: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied
+}
+
+impl Smartass for () {
+    type Data2 = *const [u8; 1];
+}
+
+impl Smartass for dyn MaybeObjectSafe {
+    type Data = *const [u8];
+    type Data2 = *const [u8; 0];
+}
+
+impl<U: Smartass+?Sized, T: Smartass+?Sized> CoerceUnsized<SmartassPtr<T>> for SmartassPtr<U>
+    where <U as Smartass>::Data: std::ops::CoerceUnsized<<T as Smartass>::Data>
+{}
+
+pub fn conv(s: SmartassPtr<()>) -> SmartassPtr<dyn MaybeObjectSafe> {
+    s
+}
diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr
new file mode 100644
index 00000000000..1941d40fee8
--- /dev/null
+++ b/tests/ui/specialization/issue-44861.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied
+  --> $DIR/issue-44861.rs:21:26
+   |
+LL |     default type Data2 = ();
+   |                          ^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()`
+   |
+note: required by a bound in `Smartass::Data2`
+  --> $DIR/issue-44861.rs:12:17
+   |
+LL |     type Data2: CoerceUnsized<*const [u8]>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Smartass::Data2`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/issue-45814.current.stderr b/tests/ui/specialization/issue-45814.current.stderr
new file mode 100644
index 00000000000..5013559b80e
--- /dev/null
+++ b/tests/ui/specialization/issue-45814.current.stderr
@@ -0,0 +1,14 @@
+error[E0275]: overflow evaluating the requirement `T: Trait<_>`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
+note: required for `T` to implement `Trait<_>`
+  --> $DIR/issue-45814.rs:9:20
+   |
+LL | default impl<T, U> Trait<T> for U {}
+   |                    ^^^^^^^^     ^
+   = note: 128 redundant requirements hidden
+   = note: required for `T` to implement `Trait<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/specialization/issue-45814.negative.stderr b/tests/ui/specialization/issue-45814.negative.stderr
new file mode 100644
index 00000000000..5013559b80e
--- /dev/null
+++ b/tests/ui/specialization/issue-45814.negative.stderr
@@ -0,0 +1,14 @@
+error[E0275]: overflow evaluating the requirement `T: Trait<_>`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
+note: required for `T` to implement `Trait<_>`
+  --> $DIR/issue-45814.rs:9:20
+   |
+LL | default impl<T, U> Trait<T> for U {}
+   |                    ^^^^^^^^     ^
+   = note: 128 redundant requirements hidden
+   = note: required for `T` to implement `Trait<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/specialization/issue-45814.rs b/tests/ui/specialization/issue-45814.rs
new file mode 100644
index 00000000000..fce236390c2
--- /dev/null
+++ b/tests/ui/specialization/issue-45814.rs
@@ -0,0 +1,13 @@
+//~ ERROR overflow evaluating the requirement `T: Trait<_>`
+// revisions: current negative
+#![feature(specialization)]
+#![cfg_attr(negative, feature(with_negative_coherence))]
+#![allow(incomplete_features)]
+
+pub trait Trait<T> {}
+
+default impl<T, U> Trait<T> for U {}
+
+impl<T> Trait<<T as Iterator>::Item> for T {}
+
+fn main() {}
diff --git a/tests/ui/specialization/issue-50452-fail.rs b/tests/ui/specialization/issue-50452-fail.rs
new file mode 100644
index 00000000000..fe21e9b6ede
--- /dev/null
+++ b/tests/ui/specialization/issue-50452-fail.rs
@@ -0,0 +1,21 @@
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+pub trait Foo {
+    fn foo();
+}
+
+impl Foo for i32 {}
+impl Foo for i64 {
+    fn foo() {}
+    //~^ERROR `foo` specializes an item from a parent `impl`
+}
+impl<T> Foo for T {
+    fn foo() {}
+}
+
+fn main() {
+    i32::foo();
+    i64::foo();
+    u8::foo();
+}
diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr
new file mode 100644
index 00000000000..5c136adc451
--- /dev/null
+++ b/tests/ui/specialization/issue-50452-fail.stderr
@@ -0,0 +1,24 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-50452-fail.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/issue-50452-fail.rs:10:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^^^^ cannot specialize default item `foo`
+...
+LL | impl<T> Foo for T {
+   | ----------------- parent `impl` is here
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/issue-50452.rs b/tests/ui/specialization/issue-50452.rs
new file mode 100644
index 00000000000..29fc12066e8
--- /dev/null
+++ b/tests/ui/specialization/issue-50452.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+pub trait Foo {
+    fn foo();
+}
+
+impl Foo for i32 {}
+impl Foo for i64 {}
+impl<T> Foo for T {
+    fn foo() {}
+}
+
+fn main() {
+    i32::foo();
+    i64::foo();
+    u8::foo();
+}
diff --git a/tests/ui/specialization/issue-50452.stderr b/tests/ui/specialization/issue-50452.stderr
new file mode 100644
index 00000000000..48cab9dcdb7
--- /dev/null
+++ b/tests/ui/specialization/issue-50452.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-50452.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/issue-51892.rs b/tests/ui/specialization/issue-51892.rs
new file mode 100644
index 00000000000..5c06254143d
--- /dev/null
+++ b/tests/ui/specialization/issue-51892.rs
@@ -0,0 +1,18 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![feature(specialization)]
+
+pub trait Trait {
+    type Type;
+}
+
+impl<T: ?Sized> Trait for T {
+    default type Type = [u8; 1];
+}
+
+impl<T: Trait> Trait for *const T {
+    type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
+    //~^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/issue-51892.stderr b/tests/ui/specialization/issue-51892.stderr
new file mode 100644
index 00000000000..cb46db83606
--- /dev/null
+++ b/tests/ui/specialization/issue-51892.stderr
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/issue-51892.rs:14:17
+   |
+LL |     type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/issue-52050.rs b/tests/ui/specialization/issue-52050.rs
new file mode 100644
index 00000000000..80465870206
--- /dev/null
+++ b/tests/ui/specialization/issue-52050.rs
@@ -0,0 +1,32 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Regression test for #52050: when inserting the blanket impl `I`
+// into the tree, we had to replace the child node for `Foo`, which
+// led to the structure of the tree being messed up.
+
+use std::iter::Iterator;
+
+trait IntoPyDictPointer { }
+
+struct Foo { }
+
+impl Iterator for Foo {
+    type Item = ();
+    fn next(&mut self) -> Option<()> {
+        None
+    }
+}
+
+impl IntoPyDictPointer for Foo { }
+
+impl<I> IntoPyDictPointer for I
+where
+    I: Iterator,
+{
+}
+
+impl IntoPyDictPointer for () //~ ERROR conflicting implementations
+{
+}
+
+fn main() { }
diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr
new file mode 100644
index 00000000000..c263fe46724
--- /dev/null
+++ b/tests/ui/specialization/issue-52050.stderr
@@ -0,0 +1,24 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-52050.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`
+  --> $DIR/issue-52050.rs:28:1
+   |
+LL | impl<I> IntoPyDictPointer for I
+   | ------------------------------- first implementation here
+...
+LL | impl IntoPyDictPointer for ()
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+   |
+   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/issue-59435.rs b/tests/ui/specialization/issue-59435.rs
new file mode 100644
index 00000000000..32390025662
--- /dev/null
+++ b/tests/ui/specialization/issue-59435.rs
@@ -0,0 +1,17 @@
+#![feature(specialization)]
+#![allow(incomplete_features)]
+
+struct MyStruct {}
+
+trait MyTrait {
+    type MyType: Default;
+}
+
+impl MyTrait for i32 {
+    default type MyType = MyStruct;
+    //~^ ERROR: the trait bound `MyStruct: Default` is not satisfied
+}
+
+fn main() {
+    let _x: <i32 as MyTrait>::MyType = <i32 as MyTrait>::MyType::default();
+}
diff --git a/tests/ui/specialization/issue-59435.stderr b/tests/ui/specialization/issue-59435.stderr
new file mode 100644
index 00000000000..21145940668
--- /dev/null
+++ b/tests/ui/specialization/issue-59435.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `MyStruct: Default` is not satisfied
+  --> $DIR/issue-59435.rs:11:27
+   |
+LL |     default type MyType = MyStruct;
+   |                           ^^^^^^^^ the trait `Default` is not implemented for `MyStruct`
+   |
+note: required by a bound in `MyTrait::MyType`
+  --> $DIR/issue-59435.rs:7:18
+   |
+LL |     type MyType: Default;
+   |                  ^^^^^^^ required by this bound in `MyTrait::MyType`
+help: consider annotating `MyStruct` with `#[derive(Default)]`
+   |
+LL | #[derive(Default)]
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs
new file mode 100644
index 00000000000..10f185c3351
--- /dev/null
+++ b/tests/ui/specialization/issue-63716-parse-async.rs
@@ -0,0 +1,14 @@
+// Ensure that `default async fn` will parse.
+// See issue #63716 for details.
+
+// check-pass
+// edition:2018
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+fn main() {}
+
+#[cfg(FALSE)]
+impl Foo for Bar {
+    default async fn baz() {}
+}
diff --git a/tests/ui/specialization/issue-63716-parse-async.stderr b/tests/ui/specialization/issue-63716-parse-async.stderr
new file mode 100644
index 00000000000..a00572da8f5
--- /dev/null
+++ b/tests/ui/specialization/issue-63716-parse-async.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-63716-parse-async.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs
new file mode 100644
index 00000000000..d11ec798332
--- /dev/null
+++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs
@@ -0,0 +1,23 @@
+// A regression test for #68830. This checks we don't emit
+// a verbose `conflicting implementations` error.
+
+#![feature(specialization)]
+#![allow(incomplete_features)]
+
+struct BadStruct {
+    err: MissingType //~ ERROR: cannot find type `MissingType` in this scope
+}
+
+trait MyTrait<T> {
+    fn foo();
+}
+
+impl<T, D> MyTrait<T> for D {
+    default fn foo() {}
+}
+
+impl<T> MyTrait<T> for BadStruct {
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
new file mode 100644
index 00000000000..833f61dca8c
--- /dev/null
+++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `MissingType` in this scope
+  --> $DIR/issue-68830-spurious-diagnostics.rs:8:10
+   |
+LL |     err: MissingType
+   |          ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/specialization/issue-70442.rs b/tests/ui/specialization/issue-70442.rs
new file mode 100644
index 00000000000..d41b5355c2c
--- /dev/null
+++ b/tests/ui/specialization/issue-70442.rs
@@ -0,0 +1,23 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// check-pass
+
+trait Trait {
+    type Assoc;
+}
+
+impl<T> Trait for T {
+    default type Assoc = bool;
+}
+
+// This impl inherits the `Assoc` definition from above and "locks it in", or finalizes it, making
+// child impls unable to further specialize it. However, since the specialization graph didn't
+// correctly track this, we would refuse to project `Assoc` from this impl, even though that should
+// happen for items that are final.
+impl Trait for () {}
+
+fn foo<X: Trait<Assoc=bool>>() {}
+
+fn main() {
+    foo::<()>();  // `<() as Trait>::Assoc` is normalized to `bool` correctly
+}
diff --git a/tests/ui/specialization/issue-70442.stderr b/tests/ui/specialization/issue-70442.stderr
new file mode 100644
index 00000000000..aa72c32866a
--- /dev/null
+++ b/tests/ui/specialization/issue-70442.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-70442.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs
new file mode 100644
index 00000000000..6ec0d261d51
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+pub trait SpecTrait {
+    fn method(&self);
+}
diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs
new file mode 100644
index 00000000000..03cab00b0fb
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs
@@ -0,0 +1,32 @@
+// Test that associated types in trait objects are not considered to be
+// constrained.
+
+#![feature(min_specialization)]
+
+trait Specializable {
+    fn f();
+}
+
+trait B<T> {
+    type Y;
+}
+
+trait C {
+    type Y;
+}
+
+impl<A: ?Sized> Specializable for A {
+    default fn f() {}
+}
+
+impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr
new file mode 100644
index 00000000000..db5558f16be
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr
@@ -0,0 +1,14 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:22:1
+   |
+LL | impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:27:1
+   |
+LL | impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs
new file mode 100644
index 00000000000..77a64320d6f
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs
@@ -0,0 +1,7 @@
+#![feature(min_specialization)]
+
+trait Trait {}
+impl Trait for NonExistent {}
+//~^ ERROR cannot find type `NonExistent` in this scope
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr
new file mode 100644
index 00000000000..b032ccbe53f
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `NonExistent` in this scope
+  --> $DIR/impl-on-nonexisting.rs:4:16
+   |
+LL | impl Trait for NonExistent {}
+   |                ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.rs b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs
new file mode 100644
index 00000000000..723ed71c3e9
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs
@@ -0,0 +1,16 @@
+// Check that specialization traits can't be implemented without a feature.
+
+// gate-test-min_specialization
+
+// aux-build:specialization-trait.rs
+
+extern crate specialization_trait;
+
+struct A {}
+
+impl specialization_trait::SpecTrait for A {
+    //~^ ERROR implementing `rustc_specialization_trait` traits is unstable
+    fn method(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr
new file mode 100644
index 00000000000..934103d49dc
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr
@@ -0,0 +1,10 @@
+error: implementing `rustc_specialization_trait` traits is unstable
+  --> $DIR/impl_specialization_trait.rs:11:1
+   |
+LL | impl specialization_trait::SpecTrait for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(min_specialization)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs
new file mode 100644
index 00000000000..98d7f919435
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs
@@ -0,0 +1,30 @@
+// Test that specializing on the well-formed predicates of the trait and
+// self-type of an impl is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+struct OrdOnly<T: Ord>(T);
+
+trait SpecTrait<U> {
+    fn f();
+}
+
+impl<T, U> SpecTrait<U> for T {
+    default fn f() {}
+}
+
+impl<T: Ord> SpecTrait<()> for OrdOnly<T> {
+    fn f() {}
+}
+
+impl<T: Ord> SpecTrait<OrdOnly<T>> for () {
+    fn f() {}
+}
+
+impl<T: Ord, U: Ord, V: Ord> SpecTrait<(OrdOnly<T>, OrdOnly<U>)> for &[OrdOnly<V>] {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/issue-79224.rs b/tests/ui/specialization/min_specialization/issue-79224.rs
new file mode 100644
index 00000000000..104bddd076e
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/issue-79224.rs
@@ -0,0 +1,26 @@
+#![feature(min_specialization)]
+use std::fmt::{self, Display};
+
+pub enum Cow<'a, B: ?Sized + 'a, O = <B as ToOwned>::Owned>
+where
+    B: ToOwned,
+{
+    Borrowed(&'a B),
+    Owned(O),
+}
+
+impl ToString for Cow<'_, str> {
+    fn to_string(&self) -> String {
+        String::new()
+    }
+}
+
+impl<B: ?Sized> Display for Cow<'_, B> {
+    //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+        write!(f, "foo")
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr
new file mode 100644
index 00000000000..be6f04ae62a
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/issue-79224.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `B: Clone` is not satisfied
+  --> $DIR/issue-79224.rs:18:17
+   |
+LL | impl<B: ?Sized> Display for Cow<'_, B> {
+   |                 ^^^^^^^ the trait `Clone` is not implemented for `B`
+   |
+   = note: required for `B` to implement `ToOwned`
+help: consider further restricting this bound
+   |
+LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
+   |                +++++++++++++++++++
+
+error[E0277]: the trait bound `B: Clone` is not satisfied
+  --> $DIR/issue-79224.rs:20:12
+   |
+LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+   |            ^^^^^ the trait `Clone` is not implemented for `B`
+   |
+   = note: required for `B` to implement `ToOwned`
+help: consider further restricting this bound
+   |
+LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
+   |                +++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.rs b/tests/ui/specialization/min_specialization/repeated_projection_type.rs
new file mode 100644
index 00000000000..f21f39f0669
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeated_projection_type.rs
@@ -0,0 +1,24 @@
+// Test that projection bounds can't be specialized on.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+impl<T: Id> X for T {
+    default fn f() {}
+}
+
+impl<I, V: Id<This = (I,)>> X for V {
+    //~^ ERROR cannot specialize on
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.stderr b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr
new file mode 100644
index 00000000000..a751ba79347
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on associated type `<V as Id>::This == (I,)`
+  --> $DIR/repeated_projection_type.rs:19:15
+   |
+LL | impl<I, V: Id<This = (I,)>> X for V {
+   |               ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.rs b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs
new file mode 100644
index 00000000000..49bfacec0ae
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs
@@ -0,0 +1,19 @@
+// Test that directly specializing on repeated lifetime parameters is not
+// allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<'a> X for (&'a u8, &'a u8) {
+    //~^ ERROR specializing impl repeats parameter `'a`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr
new file mode 100644
index 00000000000..16dccb10b45
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr
@@ -0,0 +1,8 @@
+error: specializing impl repeats parameter `'a`
+  --> $DIR/repeating_lifetimes.rs:14:1
+   |
+LL | impl<'a> X for (&'a u8, &'a u8) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/repeating_param.rs b/tests/ui/specialization/min_specialization/repeating_param.rs
new file mode 100644
index 00000000000..5a1c97fd321
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeating_param.rs
@@ -0,0 +1,17 @@
+// Test that specializing on two type parameters being equal is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+impl<T> X for (T, T) {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/repeating_param.stderr b/tests/ui/specialization/min_specialization/repeating_param.stderr
new file mode 100644
index 00000000000..5e6adf723b5
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/repeating_param.stderr
@@ -0,0 +1,8 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/repeating_param.rs:12:1
+   |
+LL | impl<T> X for (T, T) {
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/spec-iter.rs b/tests/ui/specialization/min_specialization/spec-iter.rs
new file mode 100644
index 00000000000..e17e9dd5f13
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/spec-iter.rs
@@ -0,0 +1,20 @@
+// Check that we can specialize on a concrete iterator type. This requires us
+// to consider which parameters in the parent impl are constrained.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait SpecFromIter<T> {
+    fn f(&self);
+}
+
+impl<'a, T: 'a, I: Iterator<Item = &'a T>> SpecFromIter<T> for I {
+    default fn f(&self) {}
+}
+
+impl<'a, T> SpecFromIter<T> for std::slice::Iter<'a, T> {
+    fn f(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs
new file mode 100644
index 00000000000..3bb2480e9e2
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs
@@ -0,0 +1,29 @@
+// Check that supertraits cannot be used to work around min_specialization
+// limitations.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+trait HasMethod {
+    fn method(&self);
+}
+
+#[rustc_unsafe_specialization_marker]
+trait Marker: HasMethod {}
+
+trait Spec {
+    fn spec_me(&self);
+}
+
+impl<T> Spec for T {
+    default fn spec_me(&self) {}
+}
+
+impl<T: Marker> Spec for T {
+    //~^ ERROR cannot specialize on trait `HasMethod`
+    fn spec_me(&self) {
+        self.method();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr
new file mode 100644
index 00000000000..ba9d6bbe300
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on trait `HasMethod`
+  --> $DIR/spec-marker-supertraits.rs:22:9
+   |
+LL | impl<T: Marker> Spec for T {
+   |         ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/spec-reference.rs b/tests/ui/specialization/min_specialization/spec-reference.rs
new file mode 100644
index 00000000000..377889e2cca
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/spec-reference.rs
@@ -0,0 +1,19 @@
+// Check that lifetime parameters are allowed in specializing impls.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait MySpecTrait {
+    fn f();
+}
+
+impl<T> MySpecTrait for T {
+    default fn f() {}
+}
+
+impl<'a, T: ?Sized> MySpecTrait for &'a T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialization_marker.rs b/tests/ui/specialization/min_specialization/specialization_marker.rs
new file mode 100644
index 00000000000..93462d02ea5
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_marker.rs
@@ -0,0 +1,17 @@
+// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits.
+
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {
+    fn f();
+    //~^ ERROR marker traits
+}
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker2 {
+    type X;
+    //~^ ERROR marker traits
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialization_marker.stderr b/tests/ui/specialization/min_specialization/specialization_marker.stderr
new file mode 100644
index 00000000000..b47c14f3c9f
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_marker.stderr
@@ -0,0 +1,15 @@
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:7:5
+   |
+LL |     fn f();
+   |     ^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:13:5
+   |
+LL |     type X;
+   |     ^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0714`.
diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.rs b/tests/ui/specialization/min_specialization/specialization_super_trait.rs
new file mode 100644
index 00000000000..145f376edf9
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_super_trait.rs
@@ -0,0 +1,18 @@
+// Test that supertraits can't be assumed in impls of
+// `rustc_specialization_trait`, as such impls would
+// allow specializing on the supertrait.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker: Default {
+    fn f();
+}
+
+impl<T: Default> SpecMarker for T {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.stderr b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr
new file mode 100644
index 00000000000..e935786624b
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on trait `Default`
+  --> $DIR/specialization_super_trait.rs:13:9
+   |
+LL | impl<T: Default> SpecMarker for T {
+   |         ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/specialization_trait.rs b/tests/ui/specialization/min_specialization/specialization_trait.rs
new file mode 100644
index 00000000000..d597278d296
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_trait.rs
@@ -0,0 +1,26 @@
+// Test that `rustc_specialization_trait` requires always applicable impls.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker {
+    fn f();
+}
+
+impl SpecMarker for &'static u8 {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+impl<T> SpecMarker for (T, T) {
+    //~^ ERROR specializing impl
+    fn f() {}
+}
+
+impl<T: Clone> SpecMarker for [T] {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialization_trait.stderr b/tests/ui/specialization/min_specialization/specialization_trait.stderr
new file mode 100644
index 00000000000..bc87ae0f8b8
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialization_trait.stderr
@@ -0,0 +1,20 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialization_trait.rs:11:1
+   |
+LL | impl SpecMarker for &'static u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/specialization_trait.rs:16:1
+   |
+LL | impl<T> SpecMarker for (T, T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot specialize on trait `Clone`
+  --> $DIR/specialization_trait.rs:21:9
+   |
+LL | impl<T: Clone> SpecMarker for [T] {
+   |         ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/specialization/min_specialization/specialize_on_marker.rs b/tests/ui/specialization/min_specialization/specialize_on_marker.rs
new file mode 100644
index 00000000000..4219bd13b18
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_marker.rs
@@ -0,0 +1,24 @@
+// Test that specializing on a `rustc_unsafe_specialization_marker` trait is
+// allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs
new file mode 100644
index 00000000000..abbab5c23db
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs
@@ -0,0 +1,27 @@
+// Test that specializing on a `rustc_specialization_trait` trait is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecTrait {
+    fn g(&self);
+}
+
+trait X {
+    fn f(&self);
+}
+
+impl<T> X for T {
+    default fn f(&self) {}
+}
+
+impl<T: SpecTrait> X for T {
+    fn f(&self) {
+        self.g();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.rs b/tests/ui/specialization/min_specialization/specialize_on_static.rs
new file mode 100644
index 00000000000..dd1b05401e6
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_static.rs
@@ -0,0 +1,18 @@
+// Test that directly specializing on `'static` is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for &'_ T {
+    default fn f() {}
+}
+
+impl X for &'static u8 {
+    //~^ ERROR cannot specialize on `'static` lifetime
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.stderr b/tests/ui/specialization/min_specialization/specialize_on_static.stderr
new file mode 100644
index 00000000000..9a16798f15c
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_static.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialize_on_static.rs:13:1
+   |
+LL | impl X for &'static u8 {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_trait.rs
new file mode 100644
index 00000000000..0588442c320
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_trait.rs
@@ -0,0 +1,20 @@
+// Test that specializing on a trait is not allowed in general.
+
+#![feature(min_specialization)]
+
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    //~^ ERROR cannot specialize on trait `SpecMarker`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.stderr b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr
new file mode 100644
index 00000000000..7b79c7eb4ad
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on trait `SpecMarker`
+  --> $DIR/specialize_on_trait.rs:15:9
+   |
+LL | impl<T: SpecMarker> X for T {
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/specialization/non-defaulted-item-fail.rs b/tests/ui/specialization/non-defaulted-item-fail.rs
new file mode 100644
index 00000000000..b7d6ac829dd
--- /dev/null
+++ b/tests/ui/specialization/non-defaulted-item-fail.rs
@@ -0,0 +1,54 @@
+#![feature(specialization, associated_type_defaults)]
+//~^ WARN the feature `specialization` is incomplete
+
+// Test that attempting to override a non-default method or one not in the
+// parent impl causes an error.
+
+trait Foo {
+    type Ty = ();
+    const CONST: u8 = 123;
+    fn foo(&self) -> bool { true }
+}
+
+// Specialization tree for Foo:
+//
+//       Box<T>              Vec<T>
+//        / \                 / \
+// Box<i32>  Box<i64>   Vec<()>  Vec<bool>
+
+impl<T> Foo for Box<T> {
+    type Ty = bool;
+    const CONST: u8 = 0;
+    fn foo(&self) -> bool { false }
+}
+
+// Allowed
+impl Foo for Box<i32> {}
+
+// Can't override a non-`default` fn
+impl Foo for Box<i64> {
+    type Ty = Vec<()>;
+//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
+    const CONST: u8 = 42;
+//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
+    fn foo(&self) -> bool { true }
+//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+}
+
+
+// Doesn't mention the item = provided body/value is used and the method is final.
+impl<T> Foo for Vec<T> {}
+
+// Allowed
+impl Foo for Vec<()> {}
+
+impl Foo for Vec<bool> {
+    type Ty = Vec<()>;
+//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
+    const CONST: u8 = 42;
+//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
+    fn foo(&self) -> bool { true }
+//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr
new file mode 100644
index 00000000000..faa14555a4f
--- /dev/null
+++ b/tests/ui/specialization/non-defaulted-item-fail.stderr
@@ -0,0 +1,79 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-defaulted-item-fail.rs:1:12
+   |
+LL | #![feature(specialization, associated_type_defaults)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:30:5
+   |
+LL | impl<T> Foo for Box<T> {
+   | ---------------------- parent `impl` is here
+...
+LL |     type Ty = Vec<()>;
+   |     ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+   |
+   = note: to specialize, `Ty` in the parent `impl` must be marked `default`
+
+error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:32:5
+   |
+LL | impl<T> Foo for Box<T> {
+   | ---------------------- parent `impl` is here
+...
+LL |     const CONST: u8 = 42;
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+   |
+   = note: to specialize, `CONST` in the parent `impl` must be marked `default`
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:34:5
+   |
+LL | impl<T> Foo for Box<T> {
+   | ---------------------- parent `impl` is here
+...
+LL |     fn foo(&self) -> bool { true }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:46:5
+   |
+LL | impl<T> Foo for Vec<T> {}
+   | ---------------------- parent `impl` is here
+...
+LL |     type Ty = Vec<()>;
+   |     ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+   |
+   = note: to specialize, `Ty` in the parent `impl` must be marked `default`
+
+error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:48:5
+   |
+LL | impl<T> Foo for Vec<T> {}
+   | ---------------------- parent `impl` is here
+...
+LL |     const CONST: u8 = 42;
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+   |
+   = note: to specialize, `CONST` in the parent `impl` must be marked `default`
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/non-defaulted-item-fail.rs:50:5
+   |
+LL | impl<T> Foo for Vec<T> {}
+   | ---------------------- parent `impl` is here
+...
+LL |     fn foo(&self) -> bool { true }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs
new file mode 100644
index 00000000000..923dec892e0
--- /dev/null
+++ b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs
@@ -0,0 +1,35 @@
+// run-pass
+
+use std::cell::RefCell;
+use std::cmp::Ordering;
+
+struct Evil<'a, 'b> {
+    values: RefCell<Vec<&'a str>>,
+    to_insert: &'b String,
+}
+
+impl<'a, 'b> PartialEq for Evil<'a, 'b> {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl<'a> PartialOrd for Evil<'a, 'a> {
+    fn partial_cmp(&self, _other: &Self) -> Option<Ordering> {
+        self.values.borrow_mut().push(self.to_insert);
+        None
+    }
+}
+
+fn main() {
+    let e;
+    let values;
+    {
+        let to_insert = String::from("Hello, world!");
+        e = Evil { values: RefCell::new(Vec::new()), to_insert: &to_insert };
+        let range = &e..=&e;
+        let _ = range == range;
+        values = e.values;
+    }
+    assert_eq!(*values.borrow(), Vec::<&str>::new());
+}
diff --git a/tests/ui/specialization/soundness/partial_ord_slice.rs b/tests/ui/specialization/soundness/partial_ord_slice.rs
new file mode 100644
index 00000000000..b9e80a48d33
--- /dev/null
+++ b/tests/ui/specialization/soundness/partial_ord_slice.rs
@@ -0,0 +1,42 @@
+// Check that we aren't using unsound specialization in slice comparisons.
+
+// run-pass
+
+use std::cell::Cell;
+use std::cmp::Ordering;
+
+struct Evil<'a, 'b>(Cell<(&'a [i32], &'b [i32])>);
+
+impl PartialEq for Evil<'_, '_> {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl Eq for Evil<'_, '_> {}
+
+impl PartialOrd for Evil<'_, '_> {
+    fn partial_cmp(&self, _other: &Self) -> Option<Ordering> {
+        Some(Ordering::Equal)
+    }
+}
+
+impl<'a> Ord for Evil<'a, 'a> {
+    fn cmp(&self, _other: &Self) -> Ordering {
+        let (a, b) = self.0.get();
+        self.0.set((b, a));
+        Ordering::Equal
+    }
+}
+
+fn main() {
+    let x = &[1, 2, 3, 4];
+    let u = {
+        let a = Box::new([7, 8, 9, 10]);
+        let y = [Evil(Cell::new((x, &*a)))];
+        let _ = &y[..] <= &y[..];
+        let [Evil(c)] = y;
+        c.get().0
+    };
+    assert_eq!(u, &[1, 2, 3, 4]);
+}
diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.rs b/tests/ui/specialization/specialization-allowed-cross-crate.rs
new file mode 100644
index 00000000000..5d67160eb96
--- /dev/null
+++ b/tests/ui/specialization/specialization-allowed-cross-crate.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+
+// aux-build:go_trait.rs
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+extern crate go_trait;
+
+use go_trait::{Go,GoMut};
+use std::fmt::Debug;
+use std::default::Default;
+
+struct MyThingy;
+
+impl Go for MyThingy {
+    fn go(&self, arg: isize) { }
+}
+
+impl GoMut for MyThingy {
+    fn go_mut(&mut self, arg: isize) { }
+}
+
+fn main() { }
diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.stderr b/tests/ui/specialization/specialization-allowed-cross-crate.stderr
new file mode 100644
index 00000000000..3eea4a53bf5
--- /dev/null
+++ b/tests/ui/specialization/specialization-allowed-cross-crate.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-assoc-fns.rs b/tests/ui/specialization/specialization-assoc-fns.rs
new file mode 100644
index 00000000000..cbfcb4719f6
--- /dev/null
+++ b/tests/ui/specialization/specialization-assoc-fns.rs
@@ -0,0 +1,29 @@
+// run-pass
+
+// Test that non-method associated functions can be specialized
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    fn mk() -> Self;
+}
+
+impl<T: Default> Foo for T {
+    default fn mk() -> T {
+        T::default()
+    }
+}
+
+impl Foo for Vec<u8> {
+    fn mk() -> Vec<u8> {
+        vec![0]
+    }
+}
+
+fn main() {
+    let v1: Vec<i32> = Foo::mk();
+    let v2: Vec<u8> = Foo::mk();
+
+    assert!(v1.len() == 0);
+    assert!(v2.len() == 1);
+}
diff --git a/tests/ui/specialization/specialization-assoc-fns.stderr b/tests/ui/specialization/specialization-assoc-fns.stderr
new file mode 100644
index 00000000000..69f7cece79d
--- /dev/null
+++ b/tests/ui/specialization/specialization-assoc-fns.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-assoc-fns.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-basics.rs b/tests/ui/specialization/specialization-basics.rs
new file mode 100644
index 00000000000..721c934dbfa
--- /dev/null
+++ b/tests/ui/specialization/specialization-basics.rs
@@ -0,0 +1,98 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+trait Foo {
+    fn foo(&self) -> &'static str;
+}
+
+impl<T> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic"
+    }
+}
+
+impl<T: Clone> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic Clone"
+    }
+}
+
+impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+    default fn foo(&self) -> &'static str {
+        "generic pair"
+    }
+}
+
+impl<T: Clone> Foo for (T, T) {
+    default fn foo(&self) -> &'static str {
+        "generic uniform pair"
+    }
+}
+
+impl Foo for (u8, u32) {
+    default fn foo(&self) -> &'static str {
+        "(u8, u32)"
+    }
+}
+
+impl Foo for (u8, u8) {
+    default fn foo(&self) -> &'static str {
+        "(u8, u8)"
+    }
+}
+
+impl<T: Clone> Foo for Vec<T> {
+    default fn foo(&self) -> &'static str {
+        "generic Vec"
+    }
+}
+
+impl Foo for Vec<i32> {
+    fn foo(&self) -> &'static str {
+        "Vec<i32>"
+    }
+}
+
+impl Foo for String {
+    fn foo(&self) -> &'static str {
+        "String"
+    }
+}
+
+impl Foo for i32 {
+    fn foo(&self) -> &'static str {
+        "i32"
+    }
+}
+
+struct NotClone;
+
+trait MyMarker {}
+impl<T: Clone + MyMarker> Foo for T {
+    default fn foo(&self) -> &'static str {
+        "generic Clone + MyMarker"
+    }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+fn  main() {
+    assert!(NotClone.foo() == "generic");
+    assert!(0u8.foo() == "generic Clone");
+    assert!(vec![NotClone].foo() == "generic");
+    assert!(vec![0u8].foo() == "generic Vec");
+    assert!(vec![0i32].foo() == "Vec<i32>");
+    assert!(0i32.foo() == "i32");
+    assert!(String::new().foo() == "String");
+    assert!(((), 0).foo() == "generic pair");
+    assert!(((), ()).foo() == "generic uniform pair");
+    assert!((0u8, 0u32).foo() == "(u8, u32)");
+    assert!((0u8, 0u8).foo() == "(u8, u8)");
+    assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}
diff --git a/tests/ui/specialization/specialization-basics.stderr b/tests/ui/specialization/specialization-basics.stderr
new file mode 100644
index 00000000000..7714d4af4c6
--- /dev/null
+++ b/tests/ui/specialization/specialization-basics.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-basics.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-cross-crate-no-gate.rs b/tests/ui/specialization/specialization-cross-crate-no-gate.rs
new file mode 100644
index 00000000000..f744b16de7a
--- /dev/null
+++ b/tests/ui/specialization/specialization-cross-crate-no-gate.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+// Test that specialization works even if only the upstream crate enables it
+
+// aux-build:specialization_cross_crate.rs
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+fn  main() {
+    assert!(0u8.foo() == "generic Clone");
+    assert!(vec![0u8].foo() == "generic Vec");
+    assert!(vec![0i32].foo() == "Vec<i32>");
+    assert!(0i32.foo() == "i32");
+    assert!(String::new().foo() == "String");
+    assert!(((), 0).foo() == "generic pair");
+    assert!(((), ()).foo() == "generic uniform pair");
+    assert!((0u8, 0u32).foo() == "(u8, u32)");
+    assert!((0u8, 0u8).foo() == "(u8, u8)");
+}
diff --git a/tests/ui/specialization/specialization-cross-crate.rs b/tests/ui/specialization/specialization-cross-crate.rs
new file mode 100644
index 00000000000..d9381d66152
--- /dev/null
+++ b/tests/ui/specialization/specialization-cross-crate.rs
@@ -0,0 +1,50 @@
+// run-pass
+
+// aux-build:specialization_cross_crate.rs
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+struct NotClone;
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+struct MyType<T>(#[allow(unused_tuple_struct_fields)] T);
+impl<T> Foo for MyType<T> {
+    default fn foo(&self) -> &'static str {
+        "generic MyType"
+    }
+}
+
+impl Foo for MyType<u8> {
+    fn foo(&self) -> &'static str {
+        "MyType<u8>"
+    }
+}
+
+struct MyOtherType;
+impl Foo for MyOtherType {}
+
+fn  main() {
+    assert!(NotClone.foo() == "generic");
+    assert!(0u8.foo() == "generic Clone");
+    assert!(vec![NotClone].foo() == "generic");
+    assert!(vec![0u8].foo() == "generic Vec");
+    assert!(vec![0i32].foo() == "Vec<i32>");
+    assert!(0i32.foo() == "i32");
+    assert!(String::new().foo() == "String");
+    assert!(((), 0).foo() == "generic pair");
+    assert!(((), ()).foo() == "generic uniform pair");
+    assert!((0u8, 0u32).foo() == "(u8, u32)");
+    assert!((0u8, 0u8).foo() == "(u8, u8)");
+    assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+
+    assert!(MyType(()).foo() == "generic MyType");
+    assert!(MyType(0u8).foo() == "MyType<u8>");
+    assert!(MyOtherType.foo() == "generic");
+}
diff --git a/tests/ui/specialization/specialization-cross-crate.stderr b/tests/ui/specialization/specialization-cross-crate.stderr
new file mode 100644
index 00000000000..06818bb5627
--- /dev/null
+++ b/tests/ui/specialization/specialization-cross-crate.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-cross-crate.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-default-methods.rs b/tests/ui/specialization/specialization-default-methods.rs
new file mode 100644
index 00000000000..dcf68afa945
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-methods.rs
@@ -0,0 +1,87 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Test that default methods are cascaded correctly
+
+// First, test only use of explicit `default` items:
+
+trait Foo {
+    fn foo(&self) -> bool;
+}
+
+// Specialization tree for Foo:
+//
+//        T
+//       / \
+//    i32   i64
+
+impl<T> Foo for T {
+    default fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+    fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+    assert!(!0i8.foo());
+    assert!(!0i32.foo());
+    assert!(0i64.foo());
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+trait Bar {
+    fn bar(&self) -> i32 { 0 }
+}
+
+// Specialization tree for Bar.
+// Uses of $ designate that method is provided
+//
+//           $Bar   (the trait)
+//             |
+//             T
+//            /|\
+//           / | \
+//          /  |  \
+//         /   |   \
+//        /    |    \
+//       /     |     \
+//     $i32   &str  $Vec<T>
+//                    /\
+//                   /  \
+//            Vec<i32>  $Vec<i64>
+
+impl<T> Bar for T {
+    default fn bar(&self) -> i32 { 0 }
+}
+
+impl Bar for i32 {
+    fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+impl<T> Bar for Vec<T> {
+    default fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+    fn bar(&self) -> i32 { 3 }
+}
+
+fn test_bar() {
+    assert!(0u8.bar() == 0);
+    assert!(0i32.bar() == 1);
+    assert!("hello".bar() == 0);
+    assert!(vec![()].bar() == 2);
+    assert!(vec![0i32].bar() == 2);
+    assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+    test_foo();
+    test_bar();
+}
diff --git a/tests/ui/specialization/specialization-default-methods.stderr b/tests/ui/specialization/specialization-default-methods.stderr
new file mode 100644
index 00000000000..d78d30bd802
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-methods.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-methods.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-default-projection.rs b/tests/ui/specialization/specialization-default-projection.rs
new file mode 100644
index 00000000000..7f3ae951287
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-projection.rs
@@ -0,0 +1,36 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Make sure we can't project defaulted associated types
+
+trait Foo {
+    type Assoc;
+}
+
+impl<T> Foo for T {
+    default type Assoc = ();
+}
+
+impl Foo for u8 {
+    type Assoc = String;
+}
+
+fn generic<T>() -> <T as Foo>::Assoc {
+    // `T` could be some downstream crate type that specializes (or,
+    // for that matter, `u8`).
+
+    () //~ ERROR mismatched types
+}
+
+fn monomorphic() -> () {
+    // Even though we know that `()` is not specialized in a
+    // downstream crate, typeck refuses to project here.
+
+    generic::<()>() //~ ERROR mismatched types
+}
+
+fn main() {
+    // No error here, we CAN project from `u8`, as there is no `default`
+    // in that impl.
+    let s: String = generic::<u8>();
+    println!("{}", s); // bad news if this all compiles
+}
diff --git a/tests/ui/specialization/specialization-default-projection.stderr b/tests/ui/specialization/specialization-default-projection.stderr
new file mode 100644
index 00000000000..b8b81876d81
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-projection.stderr
@@ -0,0 +1,43 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-projection.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-projection.rs:21:5
+   |
+LL | fn generic<T>() -> <T as Foo>::Assoc {
+   |                    ----------------- expected `<T as Foo>::Assoc` because of return type
+...
+LL |     ()
+   |     ^^ expected associated type, found `()`
+   |
+   = note: expected associated type `<T as Foo>::Assoc`
+                    found unit type `()`
+   = help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-projection.rs:28:5
+   |
+LL | fn monomorphic() -> () {
+   |                     -- expected `()` because of return type
+...
+LL |     generic::<()>()
+   |     ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
+   |     |
+   |     expected `()`, found associated type
+   |
+   = note:    expected unit type `()`
+           found associated type `<() as Foo>::Assoc`
+   = help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-default-types.rs b/tests/ui/specialization/specialization-default-types.rs
new file mode 100644
index 00000000000..346471f11e4
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-types.rs
@@ -0,0 +1,35 @@
+// It should not be possible to use the concrete value of a defaulted
+// associated type in the impl defining it -- otherwise, what happens
+// if it's overridden?
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Example {
+    type Output;
+    fn generate(self) -> Self::Output;
+}
+
+impl<T> Example for T {
+    default type Output = Box<T>;
+    default fn generate(self) -> Self::Output {
+        Box::new(self) //~ ERROR mismatched types
+    }
+}
+
+impl Example for bool {
+    type Output = bool;
+    fn generate(self) -> bool { self }
+}
+
+fn trouble<T>(t: T) -> Box<T> {
+    Example::generate(t) //~ ERROR mismatched types
+}
+
+fn weaponize() -> bool {
+    let b: Box<bool> = trouble(true);
+    *b
+}
+
+fn main() {
+    weaponize();
+}
diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.stderr
new file mode 100644
index 00000000000..61a556a9311
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-types.stderr
@@ -0,0 +1,39 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-types.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-types.rs:15:9
+   |
+LL |     default type Output = Box<T>;
+   |     ----------------------------- expected this associated type
+LL |     default fn generate(self) -> Self::Output {
+   |                                  ------------ expected `<T as Example>::Output` because of return type
+LL |         Box::new(self)
+   |         ^^^^^^^^^^^^^^ expected associated type, found struct `Box`
+   |
+   = note: expected associated type `<T as Example>::Output`
+                       found struct `Box<T>`
+
+error[E0308]: mismatched types
+  --> $DIR/specialization-default-types.rs:25:5
+   |
+LL | fn trouble<T>(t: T) -> Box<T> {
+   |                        ------ expected `Box<T>` because of return type
+LL |     Example::generate(t)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found associated type
+   |
+   = note:       expected struct `Box<T>`
+           found associated type `<T as Example>::Output`
+   = help: consider constraining the associated type `<T as Example>::Output` to `Box<T>`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs
new file mode 100644
index 00000000000..8bad3ac0a1f
--- /dev/null
+++ b/tests/ui/specialization/specialization-feature-gate-default.rs
@@ -0,0 +1,13 @@
+// Check that specialization must be ungated to use the `default` keyword
+
+// gate-test-specialization
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl<T> Foo for T {
+    default fn foo(&self) {} //~ ERROR specialization is unstable
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr
new file mode 100644
index 00000000000..42dbb200c24
--- /dev/null
+++ b/tests/ui/specialization/specialization-feature-gate-default.stderr
@@ -0,0 +1,12 @@
+error[E0658]: specialization is unstable
+  --> $DIR/specialization-feature-gate-default.rs:10:5
+   |
+LL |     default fn foo(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: add `#![feature(specialization)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.rs b/tests/ui/specialization/specialization-feature-gate-overlap.rs
new file mode 100644
index 00000000000..b83c84ab82c
--- /dev/null
+++ b/tests/ui/specialization/specialization-feature-gate-overlap.rs
@@ -0,0 +1,17 @@
+// Check that writing an overlapping impl is not allow unless specialization is ungated.
+
+// gate-test-specialization
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+}
+
+impl Foo for u8 { //~ ERROR E0119
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.stderr b/tests/ui/specialization/specialization-feature-gate-overlap.stderr
new file mode 100644
index 00000000000..9157ad0d46a
--- /dev/null
+++ b/tests/ui/specialization/specialization-feature-gate-overlap.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `u8`
+  --> $DIR/specialization-feature-gate-overlap.rs:13:1
+   |
+LL | impl<T> Foo for T {
+   | ----------------- first implementation here
+...
+LL | impl Foo for u8 {
+   | ^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-no-default.rs b/tests/ui/specialization/specialization-no-default.rs
new file mode 100644
index 00000000000..ae739b2358d
--- /dev/null
+++ b/tests/ui/specialization/specialization-no-default.rs
@@ -0,0 +1,77 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+// Test 1: one layer of specialization, multiple methods, missing `default`
+
+trait Foo {
+    fn foo(&self);
+    fn bar(&self);
+}
+
+impl<T> Foo for T {
+    fn foo(&self) {}
+    fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+    fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+    fn bar(&self) {} //~ ERROR E0520
+}
+
+// Test 2: one layer of specialization, missing `default` on associated type
+
+trait Bar {
+    type T;
+}
+
+impl<T> Bar for T {
+    type T = u8;
+}
+
+impl Bar for u8 {
+    type T = (); //~ ERROR E0520
+}
+
+// Test 3a: multiple layers of specialization, missing interior `default`
+
+trait Baz {
+    fn baz(&self);
+}
+
+impl<T> Baz for T {
+    default fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+    fn baz(&self) {}
+}
+
+impl Baz for i32 {
+    fn baz(&self) {} //~ ERROR E0520
+}
+
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+
+trait Redundant {
+    fn redundant(&self);
+}
+
+impl<T> Redundant for T {
+    default fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+    fn redundant(&self) {}
+}
+
+impl Redundant for i32 {
+    default fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr
new file mode 100644
index 00000000000..842cec9c79f
--- /dev/null
+++ b/tests/ui/specialization/specialization-no-default.stderr
@@ -0,0 +1,68 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:20:5
+   |
+LL | impl<T> Foo for T {
+   | ----------------- parent `impl` is here
+...
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:23:5
+   |
+LL | impl<T> Foo for T {
+   | ----------------- parent `impl` is here
+...
+LL |     fn bar(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |
+   = note: to specialize, `bar` in the parent `impl` must be marked `default`
+
+error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:37:5
+   |
+LL | impl<T> Bar for T {
+   | ----------------- parent `impl` is here
+...
+LL |     type T = ();
+   |     ^^^^^^^^^^^^ cannot specialize default item `T`
+   |
+   = note: to specialize, `T` in the parent `impl` must be marked `default`
+
+error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:55:5
+   |
+LL | impl<T: Clone> Baz for T {
+   | ------------------------ parent `impl` is here
+...
+LL |     fn baz(&self) {}
+   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |
+   = note: to specialize, `baz` in the parent `impl` must be marked `default`
+
+error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/specialization-no-default.rs:74:5
+   |
+LL | impl<T: Clone> Redundant for T {
+   | ------------------------------ parent `impl` is here
+...
+LL |     default fn redundant(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |
+   = note: to specialize, `redundant` in the parent `impl` must be marked `default`
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/specialization-on-projection.rs b/tests/ui/specialization/specialization-on-projection.rs
new file mode 100644
index 00000000000..be8dcc4232e
--- /dev/null
+++ b/tests/ui/specialization/specialization-on-projection.rs
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(dead_code)]
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Ensure that specialization works for impls defined directly on a projection
+
+trait Foo<T> {}
+
+trait Assoc {
+    type Item;
+}
+
+impl<T: Assoc> Foo<T::Item> for T {}
+
+struct Struct;
+
+impl Assoc for Struct {
+    type Item = u8;
+}
+
+impl Foo<u8> for Struct {}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-on-projection.stderr b/tests/ui/specialization/specialization-on-projection.stderr
new file mode 100644
index 00000000000..00fc7ffc547
--- /dev/null
+++ b/tests/ui/specialization/specialization-on-projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-on-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs
new file mode 100644
index 00000000000..cb7563e2760
--- /dev/null
+++ b/tests/ui/specialization/specialization-out-of-order.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+// Test that you can list the more specific impl before the more general one.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo {
+    type Out;
+}
+
+impl Foo for bool {
+    type Out = ();
+}
+
+impl<T> Foo for T {
+    default type Out = bool;
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-out-of-order.stderr b/tests/ui/specialization/specialization-out-of-order.stderr
new file mode 100644
index 00000000000..b524e00f01c
--- /dev/null
+++ b/tests/ui/specialization/specialization-out-of-order.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-overlap-hygiene.rs b/tests/ui/specialization/specialization-overlap-hygiene.rs
new file mode 100644
index 00000000000..93e7c83253e
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-hygiene.rs
@@ -0,0 +1,23 @@
+#![feature(decl_macro)]
+
+struct X;
+
+macro_rules! define_f_legacy { () => {
+    fn f() {}
+}}
+macro define_g_modern() {
+    fn g() {}
+}
+
+impl X {
+   fn f() {} //~ ERROR duplicate definitions with name `f`
+   fn g() {} // OK
+}
+impl X {
+    define_f_legacy!();
+}
+impl X {
+    define_g_modern!();
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-hygiene.stderr b/tests/ui/specialization/specialization-overlap-hygiene.stderr
new file mode 100644
index 00000000000..81efd46cc7f
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-hygiene.stderr
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `f`
+  --> $DIR/specialization-overlap-hygiene.rs:13:4
+   |
+LL |     fn f() {}
+   |     ------ other definition for `f`
+...
+LL |    fn f() {}
+   |    ^^^^^^ duplicate definitions for `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs
new file mode 100644
index 00000000000..550d3708295
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-negative.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait MyTrait {}
+
+struct TestType<T>(::std::marker::PhantomData<T>);
+
+unsafe impl<T: Clone> Send for TestType<T> {}
+impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0751
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr
new file mode 100644
index 00000000000..1fe4869ff54
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-negative.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-negative.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`:
+  --> $DIR/specialization-overlap-negative.rs:9:1
+   |
+LL | unsafe impl<T: Clone> Send for TestType<T> {}
+   | ------------------------------------------ positive implementation here
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs
new file mode 100644
index 00000000000..b07efb2a5c1
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-projection.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+// Test that impls on projected self types can resolve overlap, even when the
+// projections involve specialization, so long as the associated type is
+// provided by the most specialized impl.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Assoc {
+    type Output;
+}
+
+impl<T> Assoc for T {
+    default type Output = bool;
+}
+
+impl Assoc for u8 { type Output = u8; }
+impl Assoc for u16 { type Output = u16; }
+
+trait Foo {}
+impl Foo for u32 {}
+impl Foo for <u8 as Assoc>::Output {}
+impl Foo for <u16 as Assoc>::Output {}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr
new file mode 100644
index 00000000000..708c0817fd9
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-overlap.rs b/tests/ui/specialization/specialization-overlap.rs
new file mode 100644
index 00000000000..6bee22ceb8b
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap.rs
@@ -0,0 +1,19 @@
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Foo { fn foo() {} }
+impl<T: Clone> Foo for T {}
+impl<T> Foo for Vec<T> {} //~ ERROR E0119
+
+trait Bar { fn bar() {} }
+impl<T> Bar for (T, u8) {}
+impl<T> Bar for (u8, T) {} //~ ERROR E0119
+
+trait Baz<U> { fn baz() {} }
+impl<T> Baz<T> for u8 {}
+impl<T> Baz<u8> for T {} //~ ERROR E0119
+
+trait Qux { fn qux() {} }
+impl<T: Clone> Qux for T {}
+impl<T: Eq> Qux for T {} //~ ERROR E0119
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap.stderr b/tests/ui/specialization/specialization-overlap.stderr
new file mode 100644
index 00000000000..098bf4a70ab
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap.stderr
@@ -0,0 +1,45 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Foo` for type `Vec<_>`
+  --> $DIR/specialization-overlap.rs:5:1
+   |
+LL | impl<T: Clone> Foo for T {}
+   | ------------------------ first implementation here
+LL | impl<T> Foo for Vec<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Vec<_>`
+
+error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`
+  --> $DIR/specialization-overlap.rs:9:1
+   |
+LL | impl<T> Bar for (T, u8) {}
+   | ----------------------- first implementation here
+LL | impl<T> Bar for (u8, T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)`
+
+error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`
+  --> $DIR/specialization-overlap.rs:13:1
+   |
+LL | impl<T> Baz<T> for u8 {}
+   | --------------------- first implementation here
+LL | impl<T> Baz<u8> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
+
+error[E0119]: conflicting implementations of trait `Qux`
+  --> $DIR/specialization-overlap.rs:17:1
+   |
+LL | impl<T: Clone> Qux for T {}
+   | ------------------------ first implementation here
+LL | impl<T: Eq> Qux for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-polarity.rs b/tests/ui/specialization/specialization-polarity.rs
new file mode 100644
index 00000000000..b3cd8255bb9
--- /dev/null
+++ b/tests/ui/specialization/specialization-polarity.rs
@@ -0,0 +1,17 @@
+// Make sure specialization cannot change impl polarity
+
+#![feature(auto_traits)]
+#![feature(negative_impls)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+auto trait Foo {}
+
+impl<T> Foo for T {}
+impl !Foo for u8 {} //~ ERROR E0751
+
+auto trait Bar {}
+
+impl<T> !Bar for T {}
+impl Bar for u8 {} //~ ERROR E0751
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-polarity.stderr b/tests/ui/specialization/specialization-polarity.stderr
new file mode 100644
index 00000000000..f287018ba7f
--- /dev/null
+++ b/tests/ui/specialization/specialization-polarity.stderr
@@ -0,0 +1,29 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-polarity.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`:
+  --> $DIR/specialization-polarity.rs:10:1
+   |
+LL | impl<T> Foo for T {}
+   | ----------------- positive implementation here
+LL | impl !Foo for u8 {}
+   | ^^^^^^^^^^^^^^^^ negative implementation here
+
+error[E0751]: found both positive and negative implementation of trait `Bar` for type `u8`:
+  --> $DIR/specialization-polarity.rs:15:1
+   |
+LL | impl<T> !Bar for T {}
+   | ------------------ negative implementation here
+LL | impl Bar for u8 {}
+   | ^^^^^^^^^^^^^^^ positive implementation here
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/specialization/specialization-projection-alias.rs b/tests/ui/specialization/specialization-projection-alias.rs
new file mode 100644
index 00000000000..f1f0b47bb65
--- /dev/null
+++ b/tests/ui/specialization/specialization-projection-alias.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Regression test for ICE when combining specialized associated types and type
+// aliases
+
+trait Id_ {
+    type Out;
+}
+
+type Id<T> = <T as Id_>::Out;
+
+impl<T> Id_ for T {
+    default type Out = T;
+}
+
+fn test_proection() {
+    let x: Id<bool> = panic!();
+}
+
+fn main() {
+
+}
diff --git a/tests/ui/specialization/specialization-projection-alias.stderr b/tests/ui/specialization/specialization-projection-alias.stderr
new file mode 100644
index 00000000000..c94d9ed07b1
--- /dev/null
+++ b/tests/ui/specialization/specialization-projection-alias.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection-alias.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-projection.rs b/tests/ui/specialization/specialization-projection.rs
new file mode 100644
index 00000000000..78afe7a9495
--- /dev/null
+++ b/tests/ui/specialization/specialization-projection.rs
@@ -0,0 +1,42 @@
+// run-pass
+#![allow(dead_code)]
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Make sure we *can* project non-defaulted associated types
+// cf ui/specialization/specialization-default-projection.rs
+
+// First, do so without any use of specialization
+
+trait Foo {
+    type Assoc;
+}
+
+impl<T> Foo for T {
+    type Assoc = ();
+}
+
+fn generic_foo<T>() -> <T as Foo>::Assoc {
+    ()
+}
+
+// Next, allow for one layer of specialization
+
+trait Bar {
+    type Assoc;
+}
+
+impl<T> Bar for T {
+    default type Assoc = ();
+}
+
+impl<T: Clone> Bar for T {
+    type Assoc = u8;
+}
+
+fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc {
+    0u8
+}
+
+fn main() {
+}
diff --git a/tests/ui/specialization/specialization-projection.stderr b/tests/ui/specialization/specialization-projection.stderr
new file mode 100644
index 00000000000..bfc4e0a0f5d
--- /dev/null
+++ b/tests/ui/specialization/specialization-projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs
new file mode 100644
index 00000000000..fb85d801921
--- /dev/null
+++ b/tests/ui/specialization/specialization-supertraits.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+// Test that you can specialize via an explicit trait hierarchy
+
+// FIXME: this doesn't work yet...
+
+trait Parent {}
+trait Child: Parent {}
+
+trait Foo {}
+
+impl<T: Parent> Foo for T {}
+impl<T: Child> Foo for T {}
+
+fn main() {}
diff --git a/tests/ui/specialization/specialization-supertraits.stderr b/tests/ui/specialization/specialization-supertraits.stderr
new file mode 100644
index 00000000000..e716bc21596
--- /dev/null
+++ b/tests/ui/specialization/specialization-supertraits.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-supertraits.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs
new file mode 100644
index 00000000000..904aeaa088b
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Iterator {
+    fn next(&self);
+}
+
+trait WithAssoc {
+    type Item;
+}
+
+impl<'a> WithAssoc for &'a () {
+    type Item = &'a u32;
+}
+
+struct Cloned<I>(#[allow(unused_tuple_struct_fields)] I);
+
+impl<'a, I, T: 'a> Iterator for Cloned<I>
+    where I: WithAssoc<Item=&'a T>, T: Clone
+{
+    fn next(&self) {}
+}
+
+impl<'a, I, T: 'a> Iterator for Cloned<I>
+    where I: WithAssoc<Item=&'a T>, T: Copy
+{
+
+}
+
+fn main() {
+    Cloned(&()).next();
+}
diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
new file mode 100644
index 00000000000..c7aad3c0fee
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.rs b/tests/ui/specialization/specialization-translate-projections-with-params.rs
new file mode 100644
index 00000000000..62d63590a66
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections-with-params.rs
@@ -0,0 +1,32 @@
+// run-pass
+
+// Ensure that provided items are inherited properly even when impls vary in
+// type parameters *and* rely on projections, and the type parameters are input
+// types on the trait.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Trait<T> {
+    fn convert(&self) -> T;
+}
+trait WithAssoc {
+    type Item;
+    fn as_item(&self) -> &Self::Item;
+}
+
+impl<T, U> Trait<U> for T where T: WithAssoc<Item=U>, U: Clone {
+    fn convert(&self) -> U {
+        self.as_item().clone()
+    }
+}
+
+impl WithAssoc for u8 {
+    type Item = u8;
+    fn as_item(&self) -> &u8 { self }
+}
+
+impl Trait<u8> for u8 {}
+
+fn main() {
+    assert!(3u8.convert() == 3u8);
+}
diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.stderr b/tests/ui/specialization/specialization-translate-projections-with-params.stderr
new file mode 100644
index 00000000000..1c4fd9325a6
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections-with-params.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-params.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/specialization-translate-projections.rs b/tests/ui/specialization/specialization-translate-projections.rs
new file mode 100644
index 00000000000..92ea9e2b85d
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+// Ensure that provided items are inherited properly even when impls vary in
+// type parameters *and* rely on projections.
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+use std::convert::Into;
+
+trait Trait {
+    fn to_u8(&self) -> u8;
+}
+trait WithAssoc {
+    type Item;
+    fn to_item(&self) -> Self::Item;
+}
+
+impl<T, U> Trait for T where T: WithAssoc<Item=U>, U: Into<u8> {
+    fn to_u8(&self) -> u8 {
+        self.to_item().into()
+    }
+}
+
+impl WithAssoc for u8 {
+    type Item = u8;
+    fn to_item(&self) -> u8 { *self }
+}
+
+impl Trait for u8 {}
+
+fn main() {
+    assert!(3u8.to_u8() == 3u8);
+}
diff --git a/tests/ui/specialization/specialization-translate-projections.stderr b/tests/ui/specialization/specialization-translate-projections.stderr
new file mode 100644
index 00000000000..22bbb12a09b
--- /dev/null
+++ b/tests/ui/specialization/specialization-translate-projections.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/specialization/transmute-specialization.rs b/tests/ui/specialization/transmute-specialization.rs
new file mode 100644
index 00000000000..499334d983b
--- /dev/null
+++ b/tests/ui/specialization/transmute-specialization.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+fn main() {
+    unsafe {
+        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
+    }
+}
diff --git a/tests/ui/specialization/transmute-specialization.stderr b/tests/ui/specialization/transmute-specialization.stderr
new file mode 100644
index 00000000000..b1c26d7dacc
--- /dev/null
+++ b/tests/ui/specialization/transmute-specialization.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/transmute-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+