about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-05-30 17:21:25 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2020-06-20 14:34:50 +0100
commitd660dbc630b1678fadfdd60c4d8e96d3de724b0d (patch)
treea1886b5f49133548c5086476324029553cb6d480
parent04e589ced8a48818f93d6daff94a4f85e3b07271 (diff)
downloadrust-d660dbc630b1678fadfdd60c4d8e96d3de724b0d.tar.gz
rust-d660dbc630b1678fadfdd60c4d8e96d3de724b0d.zip
Check associated type satisfy their bounds
This was currently only happening due to eager normalization, which
isn't possible if there's specialization or bound variables.
-rw-r--r--src/librustc_typeck/check/compare_method.rs158
-rw-r--r--src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs32
-rw-r--r--src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr26
-rw-r--r--src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs21
-rw-r--r--src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr28
-rw-r--r--src/test/ui/generic-associated-types/issue-68643-broken-mir.rs21
-rw-r--r--src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr28
-rw-r--r--src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs21
-rw-r--r--src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr28
-rw-r--r--src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs21
-rw-r--r--src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr28
-rw-r--r--src/test/ui/generic-associated-types/issue-68656-unsized-values.rs22
-rw-r--r--src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr30
-rw-r--r--src/test/ui/issues/issue-38091.rs2
-rw-r--r--src/test/ui/issues/issue-38091.stderr12
-rw-r--r--src/test/ui/specialization/deafult-associated-type-bound-1.rs24
-rw-r--r--src/test/ui/specialization/deafult-associated-type-bound-1.stderr21
-rw-r--r--src/test/ui/specialization/deafult-associated-type-bound-2.rs22
-rw-r--r--src/test/ui/specialization/deafult-associated-type-bound-2.stderr23
-rw-r--r--src/test/ui/specialization/deafult-generic-associated-type-bound.rs27
-rw-r--r--src/test/ui/specialization/deafult-generic-associated-type-bound.stderr36
21 files changed, 625 insertions, 6 deletions
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index b39cfcb3775..98c341f4bed 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -4,15 +4,17 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::util::ExplicitSelf;
-use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
+use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
+use std::iter;
 
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
@@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>(
     let _: Result<(), ErrorReported> = (|| {
         compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
 
-        compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
+        compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
+
+        compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
     })();
 }
 
 /// The equivalent of [compare_predicate_entailment], but for associated types
 /// instead of associated functions.
-fn compare_type_predicate_entailment(
+fn compare_type_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_ty: &ty::AssocItem,
     impl_ty_span: Span,
@@ -1165,6 +1169,152 @@ fn compare_type_predicate_entailment(
     })
 }
 
+/// Validate that `ProjectionCandidate`s created for this associated type will
+/// be valid.
+///
+/// Usually given
+///
+/// trait X { type Y: Copy } impl X for T { type Y = S; }
+///
+/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
+/// impl is well-formed we have to prove `S: Copy`.
+///
+/// For default associated types the normalization is not possible (the value
+/// from the impl could be overridden). We also can't normalize generic
+/// associated types (yet) because they contain bound parameters.
+fn compare_projection_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ty: &ty::AssocItem,
+    impl_ty: &ty::AssocItem,
+    impl_ty_span: Span,
+    impl_trait_ref: ty::TraitRef<'tcx>,
+) -> Result<(), ErrorReported> {
+    let is_gat = !tcx.generics_of(impl_ty.def_id).params.is_empty();
+    if impl_ty.defaultness.is_final() && !is_gat {
+        // For "final", non-generic associate type implementations, we
+        // don't need this as described above.
+        return Ok(());
+    }
+
+    let param_env = tcx.param_env(impl_ty.def_id);
+
+    let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.container.id());
+    let impl_ty_value = tcx.type_of(impl_ty.def_id);
+
+    // Map the predicate from the trait to the corresponding one for the impl.
+    // For example:
+    //
+    // trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
+    // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
+    //
+    // For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
+    // function would translate and partially normalize
+    // `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
+    let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
+        let normalized_self = if !is_gat {
+            // projection_predicates only includes projections where the
+            // substs of the trait ref are exactly the trait's identity
+            // substs, so we can simply return the value from the impl.
+            impl_ty_value
+        } else {
+            let predicate_self_ty = predicate_substs.type_at(0);
+            let impl_ty_substs = if let ty::Projection(p) = predicate_self_ty.kind {
+                assert!(
+                    p.item_def_id == trait_ty.def_id,
+                    "projection_predicates returned predicate for the wrong type: {}",
+                    predicate_self_ty,
+                );
+                p.substs.rebase_onto(tcx, impl_trait_ref.def_id, impl_substs)
+            } else {
+                bug!(
+                    "projection_predicates returned predicate for the wrong type `{}`",
+                    predicate_self_ty,
+                );
+            };
+            impl_ty_value.subst(tcx, impl_ty_substs)
+        };
+
+        tcx.mk_substs(
+            iter::once(normalized_self.into())
+                .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, impl_trait_ref.substs))),
+        )
+    };
+
+    tcx.infer_ctxt().enter(move |infcx| {
+        let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
+        let infcx = &inh.infcx;
+        let mut selcx = traits::SelectionContext::new(&infcx);
+
+        let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
+        let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
+        let cause = ObligationCause::new(
+            impl_ty_span,
+            impl_ty_hir_id,
+            ObligationCauseCode::ItemObligation(trait_ty.def_id),
+        );
+
+        let predicates = tcx.projection_predicates(trait_ty.def_id);
+
+        debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
+
+        for predicate in predicates {
+            let concrete_ty_predicate = match predicate.kind() {
+                ty::PredicateKind::Trait(poly_tr, c) => poly_tr
+                    .map_bound(|tr| {
+                        let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
+                        ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
+                    })
+                    .with_constness(*c)
+                    .to_predicate(tcx),
+                ty::PredicateKind::Projection(poly_projection) => poly_projection
+                    .map_bound(|projection| {
+                        let projection_substs =
+                            translate_predicate_substs(projection.projection_ty.substs);
+                        ty::ProjectionPredicate {
+                            projection_ty: ty::ProjectionTy {
+                                substs: projection_substs,
+                                item_def_id: projection.projection_ty.item_def_id,
+                            },
+                            ty: projection.ty.subst(tcx, impl_trait_ref.substs),
+                        }
+                    })
+                    .to_predicate(tcx),
+                _ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
+            };
+
+            let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
+                &mut selcx,
+                param_env,
+                normalize_cause.clone(),
+                &concrete_ty_predicate,
+            );
+
+            debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
+
+            inh.register_predicates(obligations);
+            inh.register_predicate(traits::Obligation::new(
+                cause.clone(),
+                param_env,
+                normalized_predicate,
+            ));
+        }
+
+        // Check that all obligations are satisfied by the implementation's
+        // version.
+        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
+            infcx.report_fulfillment_errors(errors, None, false);
+            return Err(ErrorReported);
+        }
+
+        // Finally, resolve all regions. This catches wily misuses of
+        // lifetime parameters.
+        let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+
+        Ok(())
+    })
+}
+
 fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
     match impl_item.kind {
         ty::AssocKind::Const => "const",
diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs
new file mode 100644
index 00000000000..71f9b2967dc
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs
@@ -0,0 +1,32 @@
+// Regression test for #68641
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait UnsafeCopy {
+    type Item<'a>: Copy;
+
+    fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> {
+        *item
+    }
+}
+
+impl<T> UnsafeCopy for T {
+    type Item<'a> = T;
+    //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+}
+
+fn main() {
+    let mut s = String::from("Hello world!");
+
+    let copy = String::copy(&s);
+
+    // Do we indeed point to the samme memory?
+    assert!(s.as_ptr() == copy.as_ptr());
+
+    // Any use of `copy` is certeinly UB after this
+    drop(s);
+
+    // UB UB UB UB UB!!
+    println!("{}", copy);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
new file mode 100644
index 00000000000..eeff7c340ac
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
@@ -0,0 +1,26 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68641-check-gat-bounds.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-68641-check-gat-bounds.rs:15:5
+   |
+LL | trait UnsafeCopy {
+   | ---------------- required by `UnsafeCopy`
+...
+LL |     type Item<'a> = T;
+   |     ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::marker::Copy> UnsafeCopy for T {
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs
new file mode 100644
index 00000000000..c99073c1328
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs
@@ -0,0 +1,21 @@
+// Regression test for #68642
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait Fun {
+    type F<'a>: Fn() -> u32;
+
+    fn callme<'a>(f: Self::F<'a>) -> u32 {
+        f()
+    }
+}
+
+impl<T> Fun for T {
+    type F<'a> = Self;
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
+}
+
+fn main() {
+    <fn() -> usize>::callme(|| 1);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
new file mode 100644
index 00000000000..b3d4b8d4651
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
@@ -0,0 +1,28 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68642-broken-llvm-ir.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
+  --> $DIR/issue-68642-broken-llvm-ir.rs:15:5
+   |
+LL | trait Fun {
+   | --------- required by `Fun`
+...
+LL |     type F<'a> = Self;
+   |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `T`
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::ops::Fn<()>> Fun for T {
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs
new file mode 100644
index 00000000000..24133e75ccc
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs
@@ -0,0 +1,21 @@
+// Regression test for #68643
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait Fun {
+    type F<'a>: Fn() -> u32;
+
+    fn callme<'a>(f: Self::F<'a>) -> u32 {
+        f()
+    }
+}
+
+impl<T> Fun for T {
+    type F<'a> = Self;
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
+}
+
+pub fn main() {
+    <fn()>::callme(|| {});
+}
diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr
new file mode 100644
index 00000000000..6e23fe02de8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr
@@ -0,0 +1,28 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68643-broken-mir.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
+  --> $DIR/issue-68643-broken-mir.rs:15:5
+   |
+LL | trait Fun {
+   | --------- required by `Fun`
+...
+LL |     type F<'a> = Self;
+   |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `T`
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::ops::Fn<()>> Fun for T {
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs
new file mode 100644
index 00000000000..22620c61b83
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs
@@ -0,0 +1,21 @@
+// Regression test for #68644
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait Fun {
+    type F<'a>: Fn() -> u32;
+
+    fn callme<'a>(f: Self::F<'a>) -> u32 {
+        f()
+    }
+}
+
+impl<T> Fun for T {
+    type F<'a> = Self;
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
+}
+
+fn main() {
+    <u8>::callme(0);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr
new file mode 100644
index 00000000000..234f5c8a0cc
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr
@@ -0,0 +1,28 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68644-codegen-selection.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
+  --> $DIR/issue-68644-codegen-selection.rs:15:5
+   |
+LL | trait Fun {
+   | --------- required by `Fun`
+...
+LL |     type F<'a> = Self;
+   |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `T`
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::ops::Fn<()>> Fun for T {
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs
new file mode 100644
index 00000000000..423b80e8476
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs
@@ -0,0 +1,21 @@
+// Regression test for #68645
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait Fun {
+    type F<'a>: Fn() -> u32;
+
+    fn callme<'a>(f: Self::F<'a>) -> u32 {
+        f()
+    }
+}
+
+impl<T> Fun for T {
+    type F<'a> = Self;
+    //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
+}
+
+fn main() {
+    <&dyn Iterator<Item = u8>>::callme(&std::iter::once(1));
+}
diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
new file mode 100644
index 00000000000..ac2d5063fbb
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
@@ -0,0 +1,28 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68645-codegen-fulfillment.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
+  --> $DIR/issue-68645-codegen-fulfillment.rs:15:5
+   |
+LL | trait Fun {
+   | --------- required by `Fun`
+...
+LL |     type F<'a> = Self;
+   |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
+   |
+   = help: the trait `std::ops::Fn<()>` is not implemented for `T`
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::ops::Fn<()>> Fun for T {
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs
new file mode 100644
index 00000000000..4ccd42ba643
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs
@@ -0,0 +1,22 @@
+// Regression test for #68656
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete and may not
+
+trait UnsafeCopy<T: Copy> {
+    type Item<'a>: std::ops::Deref<Target = T>;
+
+    fn bug<'a>(item: &Self::Item<'a>) -> () {
+        let x: T = **item;
+        &x as *const _;
+    }
+}
+
+impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
+    type Item<'a> = T;
+    //~^ ERROR type mismatch resolving `<T as std::ops::Deref>::Target == T`
+}
+
+fn main() {
+    <&'static str>::bug(&"");
+}
diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr
new file mode 100644
index 00000000000..e4eb7991f76
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr
@@ -0,0 +1,30 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68656-unsized-values.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
+  --> $DIR/issue-68656-unsized-values.rs:16:5
+   |
+LL | trait UnsafeCopy<T: Copy> {
+   | ------------------------- required by `UnsafeCopy`
+...
+LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
+   |      - this type parameter
+LL |     type Item<'a> = T;
+   |     ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
+   |
+   = note: expected type parameter `T`
+             found associated type `<T as std::ops::Deref>::Target`
+help: consider further restricting this bound
+   |
+LL | impl<T: Copy + std::ops::Deref + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs
index c1262430502..a84391b94d1 100644
--- a/src/test/ui/issues/issue-38091.rs
+++ b/src/test/ui/issues/issue-38091.rs
@@ -1,4 +1,3 @@
-// run-pass
 #![feature(specialization)]
 //~^ WARN the feature `specialization` is incomplete
 
@@ -8,6 +7,7 @@ trait Iterate<'a> {
 }
 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) {}
 }
 
diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr
index a9855445f66..4d3369c5b64 100644
--- a/src/test/ui/issues/issue-38091.stderr
+++ b/src/test/ui/issues/issue-38091.stderr
@@ -7,5 +7,15 @@ LL | #![feature(specialization)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
 
-warning: 1 warning emitted
+error[E0277]: the trait bound `(): Valid` is not satisfied
+  --> $DIR/issue-38091.rs:8:5
+   |
+LL | trait Iterate<'a> {
+   | ----------------- required by `Iterate`
+...
+LL |     default type Ty = ();
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
+
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.rs b/src/test/ui/specialization/deafult-associated-type-bound-1.rs
new file mode 100644
index 00000000000..272a5e3fe10
--- /dev/null
+++ b/src/test/ui/specialization/deafult-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: std::clone::Clone` is not satisfied
+}
+
+pub fn main() {
+    1.unsafe_clone(None);
+}
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr
new file mode 100644
index 00000000000..8b3d6a913a7
--- /dev/null
+++ b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/deafult-associated-type-bound-1.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied
+  --> $DIR/deafult-associated-type-bound-1.rs:18:5
+   |
+LL | trait X {
+   | ------- required by `X`
+...
+LL |     default type U = str;
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.rs b/src/test/ui/specialization/deafult-associated-type-bound-2.rs
new file mode 100644
index 00000000000..0a21b1f0910
--- /dev/null
+++ b/src/test/ui/specialization/deafult-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/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr
new file mode 100644
index 00000000000..4d21f47051f
--- /dev/null
+++ b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr
@@ -0,0 +1,23 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/deafult-associated-type-bound-2.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0277]: can't compare `&'static B` with `B`
+  --> $DIR/deafult-associated-type-bound-2.rs:16:5
+   |
+LL | trait X<T> {
+   | ---------- required by `X`
+...
+LL |     default type U = &'static B;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
+   |
+   = help: the trait `std::cmp::PartialEq<B>` is not implemented for `&'static B`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs
new file mode 100644
index 00000000000..8a94ea658d2
--- /dev/null
+++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs
@@ -0,0 +1,27 @@
+// Check that default generics associated types are validated.
+
+#![feature(specialization)]
+#![feature(generic_associated_types)]
+//~^^ WARNING `specialization` is incomplete
+//~^^ WARNING the feature `generic_associated_types` is incomplete
+
+trait X {
+    type U<'a>: PartialEq<&'a Self>;
+    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/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
new file mode 100644
index 00000000000..1aac9e70d87
--- /dev/null
+++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
@@ -0,0 +1,36 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/deafult-generic-associated-type-bound.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/deafult-generic-associated-type-bound.rs:4:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0277]: can't compare `T` with `T`
+  --> $DIR/deafult-generic-associated-type-bound.rs:19:5
+   |
+LL | trait X {
+   | ------- required by `X`
+...
+LL |     default type U<'a> = &'a T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T`
+   |
+   = help: the trait `std::cmp::PartialEq` is not implemented for `T`
+   = note: required because of the requirements on the impl of `for<'a> std::cmp::PartialEq` for `&'a T`
+help: consider further restricting this bound
+   |
+LL | impl<T: 'static + std::cmp::PartialEq> X for T {
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.