about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_error_codes/error_codes/E0399.md4
-rw-r--r--src/librustc_infer/traits/project.rs43
-rw-r--r--src/librustc_typeck/check/mod.rs21
-rw-r--r--src/librustc_typeck/check/wfcheck.rs99
-rw-r--r--src/test/ui/associated-const/defaults-cyclic-fail.rs17
-rw-r--r--src/test/ui/associated-const/defaults-cyclic-fail.stderr31
-rw-r--r--src/test/ui/associated-const/defaults-cyclic-pass.rs36
-rw-r--r--src/test/ui/associated-const/defaults-not-assumed-fail.rs45
-rw-r--r--src/test/ui/associated-const/defaults-not-assumed-fail.stderr31
-rw-r--r--src/test/ui/associated-const/defaults-not-assumed-pass.rs42
-rw-r--r--src/test/ui/associated-types/associated-types-overridden-default.rs11
-rw-r--r--src/test/ui/associated-types/associated-types-overridden-default.stderr9
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-1.rs45
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-1.stderr33
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-2.rs47
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-2.stderr33
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-pass-1.rs56
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-pass-2.rs56
-rw-r--r--src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs37
-rw-r--r--src/test/ui/associated-types/defaults-in-other-trait-items.rs50
-rw-r--r--src/test/ui/associated-types/defaults-in-other-trait-items.stderr25
-rw-r--r--src/test/ui/associated-types/defaults-mixed.rs34
-rw-r--r--src/test/ui/associated-types/defaults-mixed.stderr21
-rw-r--r--src/test/ui/associated-types/defaults-specialization.rs95
-rw-r--r--src/test/ui/associated-types/defaults-specialization.stderr123
-rw-r--r--src/test/ui/associated-types/defaults-suitability.rs106
-rw-r--r--src/test/ui/associated-types/defaults-suitability.stderr140
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-1.rs63
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-1.stderr95
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-2.rs63
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-2.stderr95
-rw-r--r--src/test/ui/associated-types/issue-26681.rs20
-rw-r--r--src/test/ui/associated-types/issue-26681.stderr14
-rw-r--r--src/test/ui/associated-types/issue-32350.rs29
-rw-r--r--src/test/ui/associated-types/issue-41868.rs23
-rw-r--r--src/test/ui/associated-types/issue-43924.rs15
-rw-r--r--src/test/ui/associated-types/issue-43924.stderr23
-rw-r--r--src/test/ui/associated-types/issue-47385.rs16
-rw-r--r--src/test/ui/associated-types/issue-54182-1.rs92
-rw-r--r--src/test/ui/associated-types/issue-54182-2.rs19
-rw-r--r--src/test/ui/associated-types/issue-63593.rs13
-rw-r--r--src/test/ui/associated-types/issue-63593.stderr14
-rw-r--r--src/test/ui/associated-types/issue-65774-1.rs58
-rw-r--r--src/test/ui/associated-types/issue-65774-1.stderr17
-rw-r--r--src/test/ui/associated-types/issue-65774-2.rs58
-rw-r--r--src/test/ui/associated-types/issue-65774-2.stderr17
-rw-r--r--src/test/ui/lint/lint-missing-doc.rs2
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.rs9
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.stderr113
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.rs5
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.stderr25
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.rs4
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.stderr10
53 files changed, 2048 insertions, 154 deletions
diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md
index 71482c3ca64..6ea6054b417 100644
--- a/src/librustc_error_codes/error_codes/E0399.md
+++ b/src/librustc_error_codes/error_codes/E0399.md
@@ -1,9 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler
+
 You implemented a trait, overriding one or more of its associated types but did
 not reimplement its default methods.
 
 Example of erroneous code:
 
-```compile_fail,E0399
+```
 #![feature(associated_type_defaults)]
 
 pub trait Foo {
diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs
index a7c3e9110ab..8d9e5d3fa20 100644
--- a/src/librustc_infer/traits/project.rs
+++ b/src/librustc_infer/traits/project.rs
@@ -1054,25 +1054,40 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     // an error when we confirm the candidate
                     // (which will ultimately lead to `normalize_to_error`
                     // being invoked).
-                    node_item.item.defaultness.has_value()
+                    false
                 } else {
+                    // If we're looking at a trait *impl*, the item is
+                    // specializable if the impl or the item are marked
+                    // `default`.
                     node_item.item.defaultness.is_default()
                         || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
                 };
 
-                // Only reveal a specializable default if we're past type-checking
-                // and the obligations is monomorphic, otherwise passes such as
-                // transmute checking and polymorphic MIR optimizations could
-                // get a result which isn't correct for all monomorphizations.
-                if !is_default {
-                    true
-                } else if obligation.param_env.reveal == Reveal::All {
-                    // NOTE(eddyb) inference variables can resolve to parameters, so
-                    // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                    let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
-                    !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
-                } else {
-                    false
+                match is_default {
+                    // Non-specializable items are always projectable
+                    false => true,
+
+                    // Only reveal a specializable default if we're past type-checking
+                    // and the obligation is monomorphic, otherwise passes such as
+                    // transmute checking and polymorphic MIR optimizations could
+                    // get a result which isn't correct for all monomorphizations.
+                    true if obligation.param_env.reveal == Reveal::All => {
+                        // NOTE(eddyb) inference variables can resolve to parameters, so
+                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
+                        let poly_trait_ref =
+                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
+                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
+                    }
+
+                    true => {
+                        debug!(
+                            "assemble_candidates_from_impls: not eligible due to default: \
+                             assoc_ty={} predicate={}",
+                            selcx.tcx().def_path_str(node_item.item.def_id),
+                            obligation.predicate,
+                        );
+                        false
+                    }
                 }
             }
             super::VtableParam(..) => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4f6eb20e6eb..4ab5d8f9ad3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1964,7 +1964,6 @@ fn check_impl_items_against_trait<'tcx>(
 
     // Locate trait definition and items
     let trait_def = tcx.trait_def(impl_trait_ref.def_id);
-    let mut overridden_associated_type = None;
 
     let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
 
@@ -2046,9 +2045,6 @@ fn check_impl_items_against_trait<'tcx>(
                 hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Type {
-                        if ty_trait_item.defaultness.has_value() {
-                            overridden_associated_type = Some(impl_item);
-                        }
                         compare_ty_impl(
                             tcx,
                             &ty_impl_item,
@@ -2082,8 +2078,6 @@ fn check_impl_items_against_trait<'tcx>(
 
     // Check for missing items from trait
     let mut missing_items = Vec::new();
-    let mut invalidated_items = Vec::new();
-    let associated_type_overridden = overridden_associated_type.is_some();
     for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
         let is_implemented = trait_def
             .ancestors(tcx, impl_id)
@@ -2094,8 +2088,6 @@ fn check_impl_items_against_trait<'tcx>(
         if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
             if !trait_item.defaultness.has_value() {
                 missing_items.push(*trait_item);
-            } else if associated_type_overridden {
-                invalidated_items.push(trait_item.ident);
             }
         }
     }
@@ -2103,19 +2095,6 @@ fn check_impl_items_against_trait<'tcx>(
     if !missing_items.is_empty() {
         missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
     }
-
-    if !invalidated_items.is_empty() {
-        let invalidator = overridden_associated_type.unwrap();
-        struct_span_err!(
-            tcx.sess,
-            invalidator.span,
-            E0399,
-            "the following trait items need to be reimplemented as `{}` was overridden: `{}`",
-            invalidator.ident,
-            invalidated_items.iter().map(|name| name.to_string()).collect::<Vec<_>>().join("`, `")
-        )
-        .emit();
-    }
 }
 
 fn missing_items_err(
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 12e6087dbaf..c13e1e5b668 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -425,10 +425,109 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
 
     for_item(tcx, item).with_fcx(|fcx, _| {
         check_where_clauses(tcx, fcx, item.span, trait_def_id, None);
+        check_associated_type_defaults(fcx, trait_def_id);
+
         vec![]
     });
 }
 
+/// Checks all associated type defaults of trait `trait_def_id`.
+///
+/// Assuming the defaults are used, check that all predicates (bounds on the
+/// assoc type and where clauses on the trait) hold.
+fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) {
+    let tcx = fcx.tcx;
+    let substs = InternalSubsts::identity_for_item(tcx, trait_def_id);
+
+    // For all assoc. types with defaults, build a map from
+    // `<Self as Trait<...>>::Assoc` to the default type.
+    let map = tcx
+        .associated_items(trait_def_id)
+        .in_definition_order()
+        .filter_map(|item| {
+            if item.kind == ty::AssocKind::Type && item.defaultness.has_value() {
+                // `<Self as Trait<...>>::Assoc`
+                let proj = ty::ProjectionTy { substs, item_def_id: item.def_id };
+                let default_ty = tcx.type_of(item.def_id);
+                debug!("assoc. type default mapping: {} -> {}", proj, default_ty);
+                Some((proj, default_ty))
+            } else {
+                None
+            }
+        })
+        .collect::<FxHashMap<_, _>>();
+
+    /// Replaces projections of associated types with their default types.
+    ///
+    /// This does a "shallow substitution", meaning that defaults that refer to
+    /// other defaulted assoc. types will still refer to the projection
+    /// afterwards, not to the other default. For example:
+    ///
+    /// ```compile_fail
+    /// trait Tr {
+    ///     type A: Clone = Vec<Self::B>;
+    ///     type B = u8;
+    /// }
+    /// ```
+    ///
+    /// This will end up replacing the bound `Self::A: Clone` with
+    /// `Vec<Self::B>: Clone`, not with `Vec<u8>: Clone`. If we did a deep
+    /// substitution and ended up with the latter, the trait would be accepted.
+    /// If an `impl` then replaced `B` with something that isn't `Clone`,
+    /// suddenly the default for `A` is no longer valid. The shallow
+    /// substitution forces the trait to add a `B: Clone` bound to be accepted,
+    /// which means that an `impl` can replace any default without breaking
+    /// others.
+    ///
+    /// Note that this isn't needed for soundness: The defaults would still be
+    /// checked in any impl that doesn't override them.
+    struct DefaultNormalizer<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        map: FxHashMap<ty::ProjectionTy<'tcx>, Ty<'tcx>>,
+    }
+
+    impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> {
+        fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+            match t.kind {
+                ty::Projection(proj_ty) => {
+                    if let Some(default) = self.map.get(&proj_ty) {
+                        default
+                    } else {
+                        t.super_fold_with(self)
+                    }
+                }
+                _ => t.super_fold_with(self),
+            }
+        }
+    }
+
+    // Now take all predicates defined on the trait, replace any mention of
+    // the assoc. types with their default, and prove them.
+    // We only consider predicates that directly mention the assoc. type.
+    let mut norm = DefaultNormalizer { tcx, map };
+    let predicates = fcx.tcx.predicates_of(trait_def_id);
+    for &(orig_pred, span) in predicates.predicates.iter() {
+        let pred = orig_pred.fold_with(&mut norm);
+        if pred != orig_pred {
+            // Mentions one of the defaulted assoc. types
+            debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred);
+            let pred = fcx.normalize_associated_types_in(span, &pred);
+            let cause = traits::ObligationCause::new(
+                span,
+                fcx.body_id,
+                traits::ItemObligation(trait_def_id),
+            );
+            let obligation = traits::Obligation::new(cause, fcx.param_env, pred);
+
+            fcx.register_predicate(obligation);
+        }
+    }
+}
+
 fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     for_item(tcx, item).with_fcx(|fcx, tcx| {
         let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs
new file mode 100644
index 00000000000..9b899ee316a
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs
@@ -0,0 +1,17 @@
+// build-fail
+
+// Cyclic assoc. const defaults don't error unless *used*
+trait Tr {
+    const A: u8 = Self::B;
+    //~^ ERROR cycle detected when const-evaluating + checking `Tr::A`
+
+    const B: u8 = Self::A;
+}
+
+// This impl is *allowed* unless its assoc. consts are used
+impl Tr for () {}
+
+fn main() {
+    // This triggers the cycle error
+    assert_eq!(<() as Tr>::A, 0);
+}
diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr
new file mode 100644
index 00000000000..940182d4aa6
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr
@@ -0,0 +1,31 @@
+error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
+  --> $DIR/defaults-cyclic-fail.rs:5:5
+   |
+LL |     const A: u8 = Self::B;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires const-evaluating `Tr::A`...
+  --> $DIR/defaults-cyclic-fail.rs:5:19
+   |
+LL |     const A: u8 = Self::B;
+   |                   ^^^^^^^
+note: ...which requires const-evaluating + checking `Tr::B`...
+  --> $DIR/defaults-cyclic-fail.rs:8:5
+   |
+LL |     const B: u8 = Self::A;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating `Tr::B`...
+  --> $DIR/defaults-cyclic-fail.rs:8:19
+   |
+LL |     const B: u8 = Self::A;
+   |                   ^^^^^^^
+   = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
+note: cycle used when const-evaluating `main`
+  --> $DIR/defaults-cyclic-fail.rs:16:16
+   |
+LL |     assert_eq!(<() as Tr>::A, 0);
+   |                ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/associated-const/defaults-cyclic-pass.rs b/src/test/ui/associated-const/defaults-cyclic-pass.rs
new file mode 100644
index 00000000000..82105f25f92
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+// Cyclic assoc. const defaults don't error unless *used*
+trait Tr {
+    const A: u8 = Self::B;
+    const B: u8 = Self::A;
+}
+
+// This impl is *allowed* unless its assoc. consts are used, matching the
+// behavior without defaults.
+impl Tr for () {}
+
+// Overriding either constant breaks the cycle
+impl Tr for u8 {
+    const A: u8 = 42;
+}
+
+impl Tr for u16 {
+    const B: u8 = 0;
+}
+
+impl Tr for u32 {
+    const A: u8 = 100;
+    const B: u8 = 123;
+}
+
+fn main() {
+    assert_eq!(<u8 as Tr>::A, 42);
+    assert_eq!(<u8 as Tr>::B, 42);
+
+    assert_eq!(<u16 as Tr>::A, 0);
+    assert_eq!(<u16 as Tr>::B, 0);
+
+    assert_eq!(<u32 as Tr>::A, 100);
+    assert_eq!(<u32 as Tr>::B, 123);
+}
diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs
new file mode 100644
index 00000000000..d7a48cbd63e
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs
@@ -0,0 +1,45 @@
+// build-fail
+
+trait Tr {
+    const A: u8 = 255;
+
+    // This should not be a constant evaluation error (overflow). The value of
+    // `Self::A` must not be assumed to hold inside the trait.
+    const B: u8 = Self::A + 1;
+    //~^ ERROR any use of this value will cause an error
+}
+
+// An impl that doesn't override any constant will NOT cause a const eval error
+// just because it's defined, but only if the bad constant is used anywhere.
+// This matches the behavior without defaults.
+impl Tr for () {}
+
+// An impl that overrides either constant with a suitable value will be fine.
+impl Tr for u8 {
+    const A: u8 = 254;
+}
+
+impl Tr for u16 {
+    const B: u8 = 0;
+}
+
+impl Tr for u32 {
+    const A: u8 = 254;
+    const B: u8 = 0;
+}
+
+fn main() {
+    assert_eq!(<() as Tr>::A, 255);
+    assert_eq!(<() as Tr>::B, 0);    // causes the error above
+    //~^ ERROR evaluation of constant expression failed
+    //~| ERROR erroneous constant used
+
+    assert_eq!(<u8 as Tr>::A, 254);
+    assert_eq!(<u8 as Tr>::B, 255);
+
+    assert_eq!(<u16 as Tr>::A, 255);
+    assert_eq!(<u16 as Tr>::B, 0);
+
+    assert_eq!(<u32 as Tr>::A, 254);
+    assert_eq!(<u32 as Tr>::B, 0);
+}
diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr
new file mode 100644
index 00000000000..fe3721a9109
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr
@@ -0,0 +1,31 @@
+error: any use of this value will cause an error
+  --> $DIR/defaults-not-assumed-fail.rs:8:19
+   |
+LL |     const B: u8 = Self::A + 1;
+   |     --------------^^^^^^^^^^^-
+   |                   |
+   |                   attempt to add with overflow
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/defaults-not-assumed-fail.rs:33:5
+   |
+LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
+   |     ^^^^^^^^^^^-------------^^^^^
+   |                |
+   |                referenced constant has errors
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: erroneous constant used
+  --> $DIR/defaults-not-assumed-fail.rs:33:5
+   |
+LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/associated-const/defaults-not-assumed-pass.rs b/src/test/ui/associated-const/defaults-not-assumed-pass.rs
new file mode 100644
index 00000000000..c08e05c8a30
--- /dev/null
+++ b/src/test/ui/associated-const/defaults-not-assumed-pass.rs
@@ -0,0 +1,42 @@
+// run-pass
+
+trait Tr {
+    const A: u8 = 255;
+
+    // This should not be a constant evaluation error (overflow). The value of
+    // `Self::A` must not be assumed to hold inside the trait.
+    const B: u8 = Self::A + 1;
+}
+
+// An impl that doesn't override any constant will NOT cause a const eval error
+// just because it's defined, but only if the bad constant is used anywhere.
+// This matches the behavior without defaults.
+impl Tr for () {}
+
+// An impl that overrides either constant with a suitable value will be fine.
+impl Tr for u8 {
+    const A: u8 = 254;
+}
+
+impl Tr for u16 {
+    const B: u8 = 0;
+}
+
+impl Tr for u32 {
+    const A: u8 = 254;
+    const B: u8 = 0;
+}
+
+fn main() {
+    assert_eq!(<() as Tr>::A, 255);
+    //assert_eq!(<() as Tr>::B, 0);  // using this is an error
+
+    assert_eq!(<u8 as Tr>::A, 254);
+    assert_eq!(<u8 as Tr>::B, 255);
+
+    assert_eq!(<u16 as Tr>::A, 255);
+    assert_eq!(<u16 as Tr>::B, 0);
+
+    assert_eq!(<u32 as Tr>::A, 254);
+    assert_eq!(<u32 as Tr>::B, 0);
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs
index 629fc7a7668..3e12c922896 100644
--- a/src/test/ui/associated-types/associated-types-overridden-default.rs
+++ b/src/test/ui/associated-types/associated-types-overridden-default.rs
@@ -1,3 +1,8 @@
+// check-pass
+
+// Before RFC 2532, overriding one assoc. type default required overriding all
+// provided defaults.
+
 #![feature(associated_type_defaults)]
 
 pub trait Tr {
@@ -9,7 +14,9 @@ pub trait Tr {
 
 impl Tr for () {
     type Assoc = ();
-    //~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
 }
 
-fn main() {}
+fn main() {
+    let _: <() as Tr>::Assoc = ();
+    let _: <() as Tr>::Assoc2 = ();
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-default.stderr b/src/test/ui/associated-types/associated-types-overridden-default.stderr
deleted file mode 100644
index 79fb9a613c2..00000000000
--- a/src/test/ui/associated-types/associated-types-overridden-default.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0399]: the following trait items need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
-  --> $DIR/associated-types-overridden-default.rs:11:5
-   |
-LL |     type Assoc = ();
-   |     ^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0399`.
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs
new file mode 100644
index 00000000000..71ac914ef57
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs
@@ -0,0 +1,45 @@
+#![feature(associated_type_defaults)]
+
+// Having a cycle in assoc. type defaults is okay...
+trait Tr {
+    type A = Self::B;
+    type B = Self::A;
+}
+
+// ...but is an error in any impl that doesn't override at least one of the defaults
+impl Tr for () {}
+//~^ ERROR overflow evaluating the requirement
+
+// As soon as at least one is redefined, it works:
+impl Tr for u8 {
+    type A = u8;
+}
+
+impl Tr for u16 {
+    type B = ();
+}
+
+impl Tr for u32 {
+    type A = ();
+    type B = u8;
+}
+
+// ...but only if this actually breaks the cycle
+impl Tr for bool {
+//~^ ERROR overflow evaluating the requirement
+    type A = Box<Self::B>;
+    //~^ ERROR overflow evaluating the requirement
+}
+// (the error is shown twice for some reason)
+
+impl Tr for usize {
+//~^ ERROR overflow evaluating the requirement
+    type B = &'static Self::A;
+    //~^ ERROR overflow evaluating the requirement
+}
+
+fn main() {
+    // We don't check that the types project correctly because the cycle errors stop compilation
+    // before `main` is type-checked.
+    // `defaults-cyclic-pass-1.rs` does this.
+}
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
new file mode 100644
index 00000000000..6a8526f6aad
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
@@ -0,0 +1,33 @@
+error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-1.rs:10:6
+   |
+LL | impl Tr for () {}
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-1.rs:28:6
+   |
+LL | impl Tr for bool {
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-1.rs:35:6
+   |
+LL | impl Tr for usize {
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-1.rs:30:5
+   |
+LL |     type A = Box<Self::B>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
+  --> $DIR/defaults-cyclic-fail-1.rs:37:5
+   |
+LL |     type B = &'static Self::A;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs
new file mode 100644
index 00000000000..05091e3f498
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs
@@ -0,0 +1,47 @@
+#![feature(associated_type_defaults)]
+
+// A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults.
+
+// Having a cycle in assoc. type defaults is okay...
+trait Tr {
+    type A = Vec<Self::B>;
+    type B = Box<Self::A>;
+}
+
+// ...but is an error in any impl that doesn't override at least one of the defaults
+impl Tr for () {}
+//~^ ERROR overflow evaluating the requirement
+
+// As soon as at least one is redefined, it works:
+impl Tr for u8 {
+    type A = u8;
+}
+
+impl Tr for u16 {
+    type B = ();
+}
+
+impl Tr for u32 {
+    type A = ();
+    type B = u8;
+}
+
+// ...but only if this actually breaks the cycle
+impl Tr for bool {
+//~^ ERROR overflow evaluating the requirement
+    type A = Box<Self::B>;
+    //~^ ERROR overflow evaluating the requirement
+}
+// (the error is shown twice for some reason)
+
+impl Tr for usize {
+//~^ ERROR overflow evaluating the requirement
+    type B = &'static Self::A;
+    //~^ ERROR overflow evaluating the requirement
+}
+
+fn main() {
+    // We don't check that the types project correctly because the cycle errors stop compilation
+    // before `main` is type-checked.
+    // `defaults-cyclic-pass-2.rs` does this.
+}
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
new file mode 100644
index 00000000000..78772df9638
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
@@ -0,0 +1,33 @@
+error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-2.rs:12:6
+   |
+LL | impl Tr for () {}
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-2.rs:30:6
+   |
+LL | impl Tr for bool {
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-2.rs:37:6
+   |
+LL | impl Tr for usize {
+   |      ^^
+
+error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+  --> $DIR/defaults-cyclic-fail-2.rs:32:5
+   |
+LL |     type A = Box<Self::B>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
+  --> $DIR/defaults-cyclic-fail-2.rs:39:5
+   |
+LL |     type B = &'static Self::A;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-1.rs b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs
new file mode 100644
index 00000000000..97c6e5bade2
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs
@@ -0,0 +1,56 @@
+// check-pass
+
+#![feature(associated_type_defaults)]
+
+// Having a cycle in assoc. type defaults is okay, as long as there's no impl
+// that retains it.
+trait Tr {
+    type A = Self::B;
+    type B = Self::A;
+
+    fn f();
+}
+
+// An impl has to break the cycle to be accepted.
+impl Tr for u8 {
+    type A = u8;
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = 0u8;
+        let _: Self::B = 0u8;
+    }
+}
+
+impl Tr for String {
+    type B = ();
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = ();
+        let _: Self::B = ();
+    }
+}
+
+impl Tr for () {
+    type A = Vec<()>;
+    type B = u8;
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = Vec::<()>::new();
+        let _: Self::B = 0u8;
+    }
+}
+
+fn main() {
+    // Check that both impls now have the right types (seen from outside the impls)
+    let _: <u8 as Tr>::A = 0u8;
+    let _: <u8 as Tr>::B = 0u8;
+
+    let _: <String as Tr>::A = ();
+    let _: <String as Tr>::B = ();
+
+    let _: <() as Tr>::A = Vec::<()>::new();
+    let _: <() as Tr>::B = 0u8;
+}
diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-2.rs b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs
new file mode 100644
index 00000000000..69315a02210
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs
@@ -0,0 +1,56 @@
+// check-pass
+
+#![feature(associated_type_defaults)]
+
+// Having a cycle in assoc. type defaults is okay, as long as there's no impl
+// that retains it.
+trait Tr {
+    type A = Vec<Self::B>;
+    type B = Box<Self::A>;
+
+    fn f();
+}
+
+// An impl has to break the cycle to be accepted.
+impl Tr for u8 {
+    type A = u8;
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = 0u8;
+        let _: Self::B = Box::new(0u8);
+    }
+}
+
+impl Tr for String {
+    type B = ();
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = Vec::<()>::new();
+        let _: Self::B = ();
+    }
+}
+
+impl Tr for () {
+    type A = Vec<()>;
+    type B = u8;
+
+    fn f() {
+        // Check that the type propagates as expected (seen from inside the impl)
+        let _: Self::A = Vec::<()>::new();
+        let _: Self::B = 0u8;
+    }
+}
+
+fn main() {
+    // Check that both impls now have the right types (seen from outside the impls)
+    let _: <u8 as Tr>::A = 0u8;
+    let _: <u8 as Tr>::B = Box::new(0u8);
+
+    let _: <String as Tr>::A = Vec::<()>::new();
+    let _: <String as Tr>::B = ();
+
+    let _: <() as Tr>::A = Vec::<()>::new();
+    let _: <() as Tr>::B = 0u8;
+}
diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs
new file mode 100644
index 00000000000..a3bfcd8efe2
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs
@@ -0,0 +1,37 @@
+// check-pass
+
+#![feature(associated_type_defaults)]
+
+trait Tr {
+    type Item = u8;
+    type Container = Vec<Self::Item>;
+}
+
+impl Tr for () {}
+
+impl Tr for u16 {
+    type Item = u16;
+}
+
+impl Tr for String {
+    type Container = String;
+}
+
+impl Tr for usize {
+    type Item = u32;
+    type Container = Vec<()>;
+}
+
+fn main() {
+    let _container: <() as Tr>::Container = Vec::<u8>::new();
+    let _item: <() as Tr>::Item = 0u8;
+
+    let _container: <u16 as Tr>::Container = Vec::<u16>::new();
+    let _item: <u16 as Tr>::Item = 0u16;
+
+    let _container: <String as Tr>::Container = String::new();
+    let _item: <String as Tr>::Item = 0u8;
+
+    let _container: <usize as Tr>::Container = Vec::<()>::new();
+    let _item: <usize as Tr>::Item = 0u32;
+}
diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs
new file mode 100644
index 00000000000..9f2e8aca477
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs
@@ -0,0 +1,50 @@
+#![feature(associated_type_defaults)]
+
+// Associated type defaults may not be assumed inside the trait defining them.
+// ie. they only resolve to `<Self as Tr>::A`, not the actual type `()`
+trait Tr {
+    type A = ();
+
+    fn f(p: Self::A) {
+        let () = p;
+        //~^ ERROR mismatched types
+        //~| NOTE expected associated type, found `()`
+        //~| NOTE expected associated type `<Self as Tr>::A`
+        //~| NOTE consider constraining the associated type
+        //~| NOTE for more information, visit
+    }
+}
+
+// An impl that doesn't override the type *can* assume the default.
+impl Tr for () {
+    fn f(p: Self::A) {
+        let () = p;
+    }
+}
+
+impl Tr for u8 {
+    type A = ();
+
+    fn f(p: Self::A) {
+        let () = p;
+    }
+}
+
+trait AssocConst {
+    type Ty = u8;
+
+    // Assoc. consts also cannot assume that default types hold
+    const C: Self::Ty = 0u8;
+    //~^ ERROR mismatched types
+    //~| NOTE expected associated type, found `u8`
+    //~| NOTE expected associated type `<Self as AssocConst>::Ty`
+    //~| NOTE consider constraining the associated type
+    //~| NOTE for more information, visit
+}
+
+// An impl can, however
+impl AssocConst for () {
+    const C: Self::Ty = 0u8;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr
new file mode 100644
index 00000000000..9ecfe49c2b5
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/defaults-in-other-trait-items.rs:9:13
+   |
+LL |         let () = p;
+   |             ^^ expected associated type, found `()`
+   |
+   = note: expected associated type `<Self as Tr>::A`
+                    found unit type `()`
+   = note: consider constraining the associated type `<Self as Tr>::A` to `()` or calling a method that returns `<Self as Tr>::A`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-in-other-trait-items.rs:37:25
+   |
+LL |     const C: Self::Ty = 0u8;
+   |                         ^^^ expected associated type, found `u8`
+   |
+   = note: expected associated type `<Self as AssocConst>::Ty`
+                         found type `u8`
+   = note: consider constraining the associated type `<Self as AssocConst>::Ty` to `u8` or calling a method that returns `<Self as AssocConst>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs
new file mode 100644
index 00000000000..c91b8de39f5
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-mixed.rs
@@ -0,0 +1,34 @@
+#![feature(associated_type_defaults)]
+
+// Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly.
+
+trait Trait {
+    type Foo = u8;
+    type Bar;
+}
+
+// `Bar` must be specified
+impl Trait for () {}
+//~^ error: not all trait items implemented, missing: `Bar`
+
+impl Trait for bool {
+//~^ error: not all trait items implemented, missing: `Bar`
+    type Foo = ();
+}
+
+impl Trait for u8 {
+    type Bar = ();
+}
+
+impl Trait for u16 {
+    type Foo = String;
+    type Bar = bool;
+}
+
+fn main() {
+    let _: <u8 as Trait>::Foo = 0u8;
+    let _: <u8 as Trait>::Bar = ();
+
+    let _: <u16 as Trait>::Foo = String::new();
+    let _: <u16 as Trait>::Bar = true;
+}
diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr
new file mode 100644
index 00000000000..69ddd5f2326
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-mixed.stderr
@@ -0,0 +1,21 @@
+error[E0046]: not all trait items implemented, missing: `Bar`
+  --> $DIR/defaults-mixed.rs:11:1
+   |
+LL |     type Bar;
+   |     --------- `Bar` from trait
+...
+LL | impl Trait for () {}
+   | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation
+
+error[E0046]: not all trait items implemented, missing: `Bar`
+  --> $DIR/defaults-mixed.rs:14:1
+   |
+LL |     type Bar;
+   |     --------- `Bar` from trait
+...
+LL | impl Trait for bool {
+   | ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs
new file mode 100644
index 00000000000..d0ed718b839
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-specialization.rs
@@ -0,0 +1,95 @@
+//! Tests the interaction of associated type defaults and specialization.
+
+#![feature(associated_type_defaults, specialization)]
+
+trait Tr {
+    type Ty = u8;
+
+    fn make() -> Self::Ty {
+        0u8
+        //~^ error: mismatched types
+    }
+}
+
+struct A<T>(T);
+// In a `default impl`, assoc. types are defaulted as well,
+// so their values can't be assumed.
+default impl<T> Tr for A<T> {
+    fn make() -> u8 { 0 }
+    //~^ ERROR method `make` has an incompatible type for trait
+}
+
+struct A2<T>(T);
+// ...same, but in the method body
+default impl<T> Tr for A2<T> {
+    fn make() -> Self::Ty { 0u8 }
+    //~^ ERROR mismatched types
+}
+
+struct B<T>(T);
+// Explicitly defaulting the type does the same.
+impl<T> Tr for B<T> {
+    default type Ty = bool;
+
+    fn make() -> bool { true }
+    //~^ ERROR method `make` has an incompatible type for trait
+}
+
+struct B2<T>(T);
+// ...same, but in the method body
+impl<T> Tr for B2<T> {
+    default type Ty = bool;
+
+    fn make() -> Self::Ty { true }
+    //~^ ERROR mismatched types
+}
+
+struct C<T>(T);
+// Only the method is defaulted, so this is fine.
+impl<T> Tr for C<T> {
+    type Ty = bool;
+
+    default fn make() -> bool { true }
+}
+
+// Defaulted method *can* assume the type, if the default is kept.
+struct D<T>(T);
+impl<T> Tr for D<T> {
+    default fn make() -> u8 { 0 }
+}
+
+impl Tr for D<bool> {
+    fn make() -> u8 { 255 }
+}
+
+struct E<T>(T);
+impl<T> Tr for E<T> {
+    default type Ty = bool;
+    default fn make() -> Self::Ty { panic!(); }
+}
+
+// This impl specializes and sets `Ty`, it can rely on `Ty=String`.
+impl Tr for E<bool> {
+    type Ty = String;
+
+    fn make() -> String { String::new() }
+}
+
+fn main() {
+    // Test that we can assume the right set of assoc. types from outside the impl
+
+    // This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait.
+    // cf. https://github.com/rust-lang/rust/issues/48515
+    //let _: <A<()> as Tr>::Ty = 0u8;
+    //let _: <A2<()> as Tr>::Ty = 0u8;
+
+    let _: <B<()> as Tr>::Ty = 0u8;   //~ error: mismatched types
+    let _: <B<()> as Tr>::Ty = true;  //~ error: mismatched types
+    let _: <B2<()> as Tr>::Ty = 0u8;  //~ error: mismatched types
+    let _: <B2<()> as Tr>::Ty = true; //~ error: mismatched types
+
+    let _: <C<()> as Tr>::Ty = true;
+
+    let _: <D<()> as Tr>::Ty = 0u8;
+    let _: <D<bool> as Tr>::Ty = 0u8;
+}
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
new file mode 100644
index 00000000000..1dd536ec636
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -0,0 +1,123 @@
+error[E0053]: method `make` has an incompatible type for trait
+  --> $DIR/defaults-specialization.rs:18:18
+   |
+LL |     fn make() -> Self::Ty {
+   |                  -------- type in trait
+...
+LL |     fn make() -> u8 { 0 }
+   |                  ^^ expected associated type, found `u8`
+   |
+   = note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
+              found fn pointer `fn() -> u8`
+   = note: consider constraining the associated type `<A<T> as Tr>::Ty` to `u8` or calling a method that returns `<A<T> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0053]: method `make` has an incompatible type for trait
+  --> $DIR/defaults-specialization.rs:34:18
+   |
+LL |     fn make() -> Self::Ty {
+   |                  -------- type in trait
+...
+LL |     fn make() -> bool { true }
+   |                  ^^^^ expected associated type, found `bool`
+   |
+   = note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
+              found fn pointer `fn() -> bool`
+   = note: consider constraining the associated type `<B<T> as Tr>::Ty` to `bool` or calling a method that returns `<B<T> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:9:9
+   |
+LL |     fn make() -> Self::Ty {
+   |                  -------- expected `<Self as Tr>::Ty` because of return type
+LL |         0u8
+   |         ^^^ expected associated type, found `u8`
+   |
+   = note: expected associated type `<Self as Tr>::Ty`
+                         found type `u8`
+   = note: consider constraining the associated type `<Self as Tr>::Ty` to `u8` or calling a method that returns `<Self as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:25:29
+   |
+LL |     fn make() -> Self::Ty { 0u8 }
+   |                  --------   ^^^ expected associated type, found `u8`
+   |                  |
+   |                  expected `<A2<T> as Tr>::Ty` because of return type
+   |
+   = note: expected associated type `<A2<T> as Tr>::Ty`
+                         found type `u8`
+   = note: consider constraining the associated type `<A2<T> as Tr>::Ty` to `u8` or calling a method that returns `<A2<T> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:43:29
+   |
+LL |     fn make() -> Self::Ty { true }
+   |                  --------   ^^^^ expected associated type, found `bool`
+   |                  |
+   |                  expected `<B2<T> as Tr>::Ty` because of return type
+   |
+   = note: expected associated type `<B2<T> as Tr>::Ty`
+                         found type `bool`
+   = note: consider constraining the associated type `<B2<T> as Tr>::Ty` to `bool` or calling a method that returns `<B2<T> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:86:32
+   |
+LL |     let _: <B<()> as Tr>::Ty = 0u8;
+   |            -----------------   ^^^ expected associated type, found `u8`
+   |            |
+   |            expected due to this
+   |
+   = note: expected associated type `<B<()> as Tr>::Ty`
+                         found type `u8`
+   = note: consider constraining the associated type `<B<()> as Tr>::Ty` to `u8` or calling a method that returns `<B<()> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:87:32
+   |
+LL |     let _: <B<()> as Tr>::Ty = true;
+   |            -----------------   ^^^^ expected associated type, found `bool`
+   |            |
+   |            expected due to this
+   |
+   = note: expected associated type `<B<()> as Tr>::Ty`
+                         found type `bool`
+   = note: consider constraining the associated type `<B<()> as Tr>::Ty` to `bool` or calling a method that returns `<B<()> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:88:33
+   |
+LL |     let _: <B2<()> as Tr>::Ty = 0u8;
+   |            ------------------   ^^^ expected associated type, found `u8`
+   |            |
+   |            expected due to this
+   |
+   = note: expected associated type `<B2<()> as Tr>::Ty`
+                         found type `u8`
+   = note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `u8` or calling a method that returns `<B2<()> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error[E0308]: mismatched types
+  --> $DIR/defaults-specialization.rs:89:33
+   |
+LL |     let _: <B2<()> as Tr>::Ty = true;
+   |            ------------------   ^^^^ expected associated type, found `bool`
+   |            |
+   |            expected due to this
+   |
+   = note: expected associated type `<B2<()> as Tr>::Ty`
+                         found type `bool`
+   = note: consider constraining the associated type `<B2<()> as Tr>::Ty` to `bool` or calling a method that returns `<B2<()> as Tr>::Ty`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0053, E0308.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs
new file mode 100644
index 00000000000..2be01cba105
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-suitability.rs
@@ -0,0 +1,106 @@
+//! Checks that associated type defaults are properly validated.
+//!
+//! This means:
+//! * Default types are wfchecked
+//! * Default types are checked against where clauses on the assoc. type
+//!   (eg. `type Assoc: Clone = NotClone`), and also against where clauses on
+//!   the trait itself when possible
+
+#![feature(associated_type_defaults)]
+
+struct NotClone;
+
+// Assoc. type bounds must hold for the default type
+trait Tr {
+    type Ty: Clone = NotClone;
+    //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
+}
+
+// Where-clauses defined on the trait must also be considered
+trait Tr2 where Self::Ty: Clone {
+    //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
+    type Ty = NotClone;
+}
+
+// Independent of where-clauses (there are none here), default types must always be wf
+trait Tr3 {
+    type Ty = Vec<[u8]>;
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+}
+
+// Involved type parameters must fulfill all bounds required by defaults that mention them
+trait Foo<T> {
+    type Bar: Clone = Vec<T>;
+    //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied
+}
+
+trait Bar: Sized {
+    // `(): Foo<Self>` might hold for some possible impls but not all.
+    type Assoc: Foo<Self> = ();
+    //~^ ERROR the trait bound `(): Foo<Self>` is not satisfied
+}
+
+trait IsU8<T> {}
+impl<T> IsU8<u8> for T {}
+
+// Test that mentioning the assoc. type inside where clauses works
+trait C where
+    Vec<Self::Assoc>: Clone,
+    Self::Assoc: IsU8<Self::Assoc>,
+    bool: IsU8<Self::Assoc>,
+{
+    type Assoc = u8;
+}
+
+// Test that we get all expected errors if that default is unsuitable
+trait D where
+    Vec<Self::Assoc>: Clone,
+    //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied
+    Self::Assoc: IsU8<Self::Assoc>,
+    //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
+    bool: IsU8<Self::Assoc>,
+    //~^ ERROR the trait bound `bool: IsU8<NotClone>` is not satisfied
+{
+    type Assoc = NotClone;
+}
+
+// Test behavior of the check when defaults refer to other defaults:
+
+// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be
+// `Clone`.
+trait Foo2<T> {
+    type Bar: Clone = Vec<Self::Baz>;
+    //~^ ERROR the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
+    type Baz = T;
+}
+
+// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T`
+// because of the shallow substitution. If we did a deep substitution instead,
+// this would be accepted.
+trait Foo25<T: Clone> {
+    type Bar: Clone = Vec<Self::Baz>;
+    //~^ ERROR the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
+    type Baz = T;
+}
+
+// Adding the `Baz: Clone` bound isn't enough since the default is type
+// parameter `T`, which also might not be `Clone`.
+trait Foo3<T> where
+    Self::Bar: Clone,
+    Self::Baz: Clone,
+    //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied
+{
+    type Bar = Vec<Self::Baz>;
+    type Baz = T;
+}
+
+// This one finally works, with `Clone` bounds on all assoc. types and the type
+// parameter.
+trait Foo4<T> where
+    T: Clone,
+{
+    type Bar: Clone = Vec<Self::Baz>;
+    type Baz: Clone = T;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr
new file mode 100644
index 00000000000..60e1821b300
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-suitability.stderr
@@ -0,0 +1,140 @@
+error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:15:14
+   |
+LL | trait Tr {
+   | -------- required by `Tr`
+LL |     type Ty: Clone = NotClone;
+   |              ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone`
+
+error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:20:27
+   |
+LL | trait Tr2 where Self::Ty: Clone {
+   | --------------------------^^^^^
+   | |                         |
+   | |                         the trait `std::clone::Clone` is not implemented for `NotClone`
+   | required by `Tr2`
+
+error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:33:15
+   |
+LL | trait Foo<T> {
+   | ------------ required by `Foo`
+LL |     type Bar: Clone = Vec<T>;
+   |               ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
+   |
+help: consider restricting this type parameter with `T: std::clone::Clone`
+  --> $DIR/defaults-suitability.rs:32:11
+   |
+LL | trait Foo<T> {
+   |           ^
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<T>`
+
+error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
+  --> $DIR/defaults-suitability.rs:39:17
+   |
+LL | trait Bar: Sized {
+   | ---------------- required by `Bar`
+LL |     // `(): Foo<Self>` might hold for some possible impls but not all.
+LL |     type Assoc: Foo<Self> = ();
+   |                 ^^^^^^^^^ the trait `Foo<Self>` is not implemented for `()`
+
+error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
+  --> $DIR/defaults-suitability.rs:59:18
+   |
+LL | / trait D where
+LL | |     Vec<Self::Assoc>: Clone,
+LL | |
+LL | |     Self::Assoc: IsU8<Self::Assoc>,
+   | |                  ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
+...  |
+LL | |     type Assoc = NotClone;
+LL | | }
+   | |_- required by `D`
+
+error[E0277]: the trait bound `bool: IsU8<NotClone>` is not satisfied
+  --> $DIR/defaults-suitability.rs:61:11
+   |
+LL | / trait D where
+LL | |     Vec<Self::Assoc>: Clone,
+LL | |
+LL | |     Self::Assoc: IsU8<Self::Assoc>,
+LL | |
+LL | |     bool: IsU8<Self::Assoc>,
+   | |           ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `bool`
+...  |
+LL | |     type Assoc = NotClone;
+LL | | }
+   | |_- required by `D`
+
+error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:57:23
+   |
+LL | / trait D where
+LL | |     Vec<Self::Assoc>: Clone,
+   | |                       ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone`
+LL | |
+LL | |     Self::Assoc: IsU8<Self::Assoc>,
+...  |
+LL | |     type Assoc = NotClone;
+LL | | }
+   | |_- required by `D`
+   |
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<NotClone>`
+
+error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:72:15
+   |
+LL | trait Foo2<T> {
+   | -------------- help: consider further restricting the associated type: `where <Self as Foo2<T>>::Baz: std::clone::Clone`
+   | |
+   | required by `Foo2`
+LL |     type Bar: Clone = Vec<Self::Baz>;
+   |               ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo2<T>>::Baz`
+   |
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo2<T>>::Baz>`
+
+error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:81:15
+   |
+LL | trait Foo25<T: Clone> {
+   | ---------------------- help: consider further restricting the associated type: `where <Self as Foo25<T>>::Baz: std::clone::Clone`
+   | |
+   | required by `Foo25`
+LL |     type Bar: Clone = Vec<Self::Baz>;
+   |               ^^^^^ the trait `std::clone::Clone` is not implemented for `<Self as Foo25<T>>::Baz`
+   |
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<<Self as Foo25<T>>::Baz>`
+
+error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied
+  --> $DIR/defaults-suitability.rs:90:16
+   |
+LL | / trait Foo3<T> where
+LL | |     Self::Bar: Clone,
+LL | |     Self::Baz: Clone,
+   | |                ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
+LL | |
+...  |
+LL | |     type Baz = T;
+LL | | }
+   | |_- required by `Foo3`
+   |
+help: consider restricting this type parameter with `where T: std::clone::Clone`
+  --> $DIR/defaults-suitability.rs:88:12
+   |
+LL | trait Foo3<T> where
+   |            ^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/defaults-suitability.rs:27:5
+   |
+LL |     type Ty = Vec<[u8]>;
+   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required by `std::vec::Vec`
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs
new file mode 100644
index 00000000000..c8b4734d6ed
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs
@@ -0,0 +1,63 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/62211
+//!
+//! The old implementation of defaults did not check whether the provided
+//! default actually fulfills all bounds on the assoc. type, leading to
+//! unsoundness, demonstrated here as a use-after-free.
+//!
+//! Note that the underlying cause of this is still not yet fixed.
+//! See: https://github.com/rust-lang/rust/issues/33017
+
+#![feature(associated_type_defaults)]
+
+use std::{
+    fmt::Display,
+    ops::{AddAssign, Deref}
+};
+
+
+trait UncheckedCopy: Sized {
+    // This Output is said to be Copy. Yet we default to Self
+    // and it's accepted, not knowing if Self ineed is Copy
+    type Output: Copy
+    //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+    + Deref<Target = str>
+    //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+    + AddAssign<&'static str>
+    //~^ ERROR cannot add-assign `&'static str` to `Self`
+    + From<Self>
+    + Display = Self;
+    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+
+    // We said the Output type was Copy, so we can Copy it freely!
+    fn unchecked_copy(other: &Self::Output) -> Self::Output {
+        (*other)
+    }
+
+    fn make_origin(s: Self) -> Self::Output {
+        s.into()
+    }
+}
+
+impl<T> UncheckedCopy for T {}
+//~^ ERROR `T` doesn't implement `std::fmt::Display`
+//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
+//~| ERROR cannot add-assign `&'static str` to `T`
+//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn bug<T: UncheckedCopy>(origin: T) {
+    let origin = T::make_origin(origin);
+    let mut copy = T::unchecked_copy(&origin);
+
+    // assert we indeed have 2 strings pointing to the same buffer.
+    assert_eq!(origin.as_ptr(), copy.as_ptr());
+
+    // Drop the origin. Any use of `copy` is UB.
+    drop(origin);
+
+    copy += "This is invalid!";
+    println!("{}", copy);
+}
+
+fn main() {
+    bug(String::from("hello!"));
+}
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
new file mode 100644
index 00000000000..9c4a1260139
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
@@ -0,0 +1,95 @@
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:21:18
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     type Output: Copy
+   |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-1.rs:25:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + AddAssign<&'static str>
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:23:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + Deref<Target = str>
+   |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:28:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + Display = Self;
+   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Self`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `T`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+help: consider restricting this type parameter with `T: std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+   |
+help: consider restricting this type parameter with `T: std::ops::Deref`
+  --> $DIR/defaults-unsound-62211-1.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+  --> $DIR/defaults-unsound-62211-1.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>`
+  --> $DIR/defaults-unsound-62211-1.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+help: consider restricting this type parameter with `T: std::marker::Copy`
+  --> $DIR/defaults-unsound-62211-1.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs
new file mode 100644
index 00000000000..aa343e759a8
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs
@@ -0,0 +1,63 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/62211
+//!
+//! The old implementation of defaults did not check whether the provided
+//! default actually fulfills all bounds on the assoc. type, leading to
+//! unsoundness and ICEs, the latter being demonstrated here.
+//!
+//! Note that the underlying cause of this is still not yet fixed.
+//! See: https://github.com/rust-lang/rust/issues/33017
+
+#![feature(associated_type_defaults)]
+
+use std::{
+    fmt::Display,
+    ops::{AddAssign, Deref}
+};
+
+
+trait UncheckedCopy: Sized {
+    // This Output is said to be Copy. Yet we default to Self
+    // and it's accepted, not knowing if Self ineed is Copy
+    type Output: Copy
+    //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+    + Deref<Target = str>
+    //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+    + AddAssign<&'static str>
+    //~^ ERROR cannot add-assign `&'static str` to `Self`
+    + From<Self>
+    + Display = Self;
+    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+
+    // We said the Output type was Copy, so we can Copy it freely!
+    fn unchecked_copy(other: &Self::Output) -> Self::Output {
+        (*other)
+    }
+
+    fn make_origin(s: Self) -> Self::Output {
+        s.into()
+    }
+}
+
+impl<T> UncheckedCopy for T {}
+//~^ ERROR `T` doesn't implement `std::fmt::Display`
+//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
+//~| ERROR cannot add-assign `&'static str` to `T`
+//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn bug<T: UncheckedCopy>(origin: T) {
+    let origin = T::make_origin(origin);
+    let mut copy = T::unchecked_copy(&origin);
+
+    // assert we indeed have 2 strings pointing to the same buffer.
+    assert_eq!(origin.as_ptr(), copy.as_ptr());
+
+    // Drop the origin. Any use of `copy` is UB.
+    drop(origin);
+
+    copy += "This is invalid!";
+    println!("{}", copy);
+}
+
+fn main() {
+    bug(());
+}
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
new file mode 100644
index 00000000000..4602fbc99fa
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
@@ -0,0 +1,95 @@
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:21:18
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     type Output: Copy
+   |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-2.rs:25:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + AddAssign<&'static str>
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:23:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + Deref<Target = str>
+   |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:28:7
+   |
+LL | trait UncheckedCopy: Sized {
+   | -------------------------- required by `UncheckedCopy`
+...
+LL |     + Display = Self;
+   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Self`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `T`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+help: consider restricting this type parameter with `T: std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+   |
+help: consider restricting this type parameter with `T: std::ops::Deref`
+  --> $DIR/defaults-unsound-62211-2.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+  --> $DIR/defaults-unsound-62211-2.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>`
+  --> $DIR/defaults-unsound-62211-2.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:41:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+help: consider restricting this type parameter with `T: std::marker::Copy`
+  --> $DIR/defaults-unsound-62211-2.rs:41:6
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |      ^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-26681.rs b/src/test/ui/associated-types/issue-26681.rs
new file mode 100644
index 00000000000..a0a8c86d949
--- /dev/null
+++ b/src/test/ui/associated-types/issue-26681.rs
@@ -0,0 +1,20 @@
+#![feature(associated_type_defaults)]
+
+// This is a partial regression test for #26681, which used to fail to resolve
+// `Self` in the assoc. constant, and now fails with a type mismatch because
+// `Self::Fv` cannot be assumed to equal `u8` inside the trait.
+
+trait Foo {
+    type Bar;
+}
+
+impl Foo for u8 {
+    type Bar = ();
+}
+
+trait Baz {
+    type Fv: Foo = u8;
+    const C: <Self::Fv as Foo>::Bar = 6665;  //~ error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr
new file mode 100644
index 00000000000..da10933df92
--- /dev/null
+++ b/src/test/ui/associated-types/issue-26681.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-26681.rs:17:39
+   |
+LL |     const C: <Self::Fv as Foo>::Bar = 6665;
+   |                                       ^^^^ expected associated type, found integer
+   |
+   = note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
+                         found type `{integer}`
+   = note: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}` or calling a method that returns `<<Self as Baz>::Fv as Foo>::Bar`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-types/issue-32350.rs b/src/test/ui/associated-types/issue-32350.rs
new file mode 100644
index 00000000000..bda21eb0e0a
--- /dev/null
+++ b/src/test/ui/associated-types/issue-32350.rs
@@ -0,0 +1,29 @@
+// check-pass
+
+// This is another instance of the "normalizations don't work" issue with
+// defaulted associated types.
+
+#![feature(associated_type_defaults)]
+
+pub trait Emitter<'a> {
+    type Ctxt: 'a;
+    type CtxtBrw: 'a = &'a Self::Ctxt;
+
+    fn get_cx(&'a self) -> Self::CtxtBrw;
+}
+
+struct MyCtxt;
+
+struct MyEmitter {
+    ctxt: MyCtxt
+}
+
+impl <'a> Emitter<'a> for MyEmitter {
+    type Ctxt = MyCtxt;
+
+    fn get_cx(&'a self) -> &'a MyCtxt {
+        &self.ctxt
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-41868.rs b/src/test/ui/associated-types/issue-41868.rs
new file mode 100644
index 00000000000..52bbd1f5d28
--- /dev/null
+++ b/src/test/ui/associated-types/issue-41868.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+// Defaulted assoc. types should normalize properly in impls that don't
+// override them.
+
+#![feature(associated_type_defaults)]
+
+pub struct Foo;
+
+pub trait CanDecode: Sized {
+    type Output = Self;
+    fn read(rdr: &mut Foo) -> Option<Self::Output>;
+}
+
+impl CanDecode for u8 {
+    fn read(rdr: &mut Foo) -> Option<Self::Output> { Some(42) }
+}
+
+impl CanDecode for u16 {
+    fn read(rdr: &mut Foo) -> Option<u16> { Some(17) }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-43924.rs b/src/test/ui/associated-types/issue-43924.rs
new file mode 100644
index 00000000000..26f1183c6bd
--- /dev/null
+++ b/src/test/ui/associated-types/issue-43924.rs
@@ -0,0 +1,15 @@
+#![feature(associated_type_defaults)]
+
+// This used to cause an ICE because assoc. type defaults weren't properly
+// type-checked.
+
+trait Foo<T: Default + ToString> {
+    type Out: Default + ToString + ?Sized = dyn ToString;  //~ error: not satisfied
+}
+
+impl Foo<u32> for () {}  //~ error: not satisfied
+impl Foo<u64> for () {}  //~ error: not satisfied
+
+fn main() {
+    assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
+}
diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr
new file mode 100644
index 00000000000..75a5b3f3551
--- /dev/null
+++ b/src/test/ui/associated-types/issue-43924.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
+  --> $DIR/issue-43924.rs:7:15
+   |
+LL | trait Foo<T: Default + ToString> {
+   | -------------------------------- required by `Foo`
+LL |     type Out: Default + ToString + ?Sized = dyn ToString;
+   |               ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
+
+error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
+  --> $DIR/issue-43924.rs:10:6
+   |
+LL | impl Foo<u32> for () {}
+   |      ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
+
+error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
+  --> $DIR/issue-43924.rs:11:6
+   |
+LL | impl Foo<u64> for () {}
+   |      ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-47385.rs b/src/test/ui/associated-types/issue-47385.rs
new file mode 100644
index 00000000000..d43d674e9c3
--- /dev/null
+++ b/src/test/ui/associated-types/issue-47385.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(associated_type_defaults)]
+
+pub struct Foo;
+
+pub trait Bar: From<<Self as Bar>::Input> {
+    type Input = Self;
+}
+
+impl Bar for Foo {
+    // Will compile with explicit type:
+    // type Input = Self;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs
new file mode 100644
index 00000000000..1a1e98cbac2
--- /dev/null
+++ b/src/test/ui/associated-types/issue-54182-1.rs
@@ -0,0 +1,92 @@
+// run-pass
+
+// Tests that the return type of trait methods is correctly normalized when
+// checking that a method in an impl matches the trait definition when the
+// return type involves a defaulted associated type.
+// ie. the trait has a method with return type `-> Self::R`, and `type R = ()`,
+// but the impl leaves out the return type (resulting in `()`).
+// Note that specialization is not involved in this test; no items in
+// implementations may be overridden. If they were, the normalization wouldn't
+// happen.
+
+#![feature(associated_type_defaults)]
+
+macro_rules! overload {
+    ($a:expr, $b:expr) => {
+        overload::overload2($a, $b)
+    };
+    ($a:expr, $b:expr, $c:expr) => {
+        overload::overload3($a, $b, $c)
+    }
+}
+
+fn main() {
+    let () = overload!(42, true);
+
+    let r: f32 = overload!("Hello world", 13.0);
+    assert_eq!(r, 13.0);
+
+    let () = overload!(42, true, 42.5);
+
+    let r: i32 = overload!("Hello world", 13.0, 42);
+    assert_eq!(r, 42);
+}
+
+mod overload {
+    /// This trait has an assoc. type defaulting to `()`, and a required method returning a value
+    /// of that assoc. type.
+    pub trait Overload {
+        // type R;
+        type R = ();
+        fn overload(self) -> Self::R;
+    }
+
+    // overloads for 2 args
+    impl Overload for (i32, bool) {
+        // type R = ();
+
+        /// This function has no return type specified, and so defaults to `()`.
+        ///
+        /// This should work, but didn't, until RFC 2532 was implemented.
+        fn overload(self) /*-> Self::R*/ {
+            let (a, b) = self; // destructure args
+            println!("i32 and bool {:?}", (a, b));
+        }
+    }
+    impl<'a> Overload for (&'a str, f32) {
+        type R = f32;
+        fn overload(self) -> Self::R {
+            let (a, b) = self; // destructure args
+            println!("&str and f32 {:?}", (a, b));
+            b
+        }
+    }
+
+    // overloads for 3 args
+    impl Overload for (i32, bool, f32) {
+        // type R = ();
+        fn overload(self) /*-> Self::R*/ {
+            let (a, b, c) = self; // destructure args
+            println!("i32 and bool and f32 {:?}", (a, b, c));
+        }
+    }
+    impl<'a> Overload for (&'a str, f32, i32) {
+        type R = i32;
+        fn overload(self) -> Self::R {
+            let (a, b, c) = self; // destructure args
+            println!("&str and f32 and i32: {:?}", (a, b, c));
+            c
+        }
+    }
+
+    // overloads for more args
+    // ...
+
+    pub fn overload2<R, A, B>(a: A, b: B) -> R where (A, B): Overload<R = R> {
+        (a, b).overload()
+    }
+
+    pub fn overload3<R, A, B, C>(a: A, b: B, c: C) -> R where (A, B, C): Overload<R = R> {
+        (a, b, c).overload()
+    }
+}
diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs
new file mode 100644
index 00000000000..c88c7663136
--- /dev/null
+++ b/src/test/ui/associated-types/issue-54182-2.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// Before RFC 2532, normalizing a defaulted assoc. type didn't work at all,
+// unless the impl in question overrides that type, which makes the default
+// pointless.
+
+#![feature(associated_type_defaults)]
+
+trait Tr {
+    type Assoc = ();
+}
+
+impl Tr for () {}
+
+fn f(thing: <() as Tr>::Assoc) {
+    let c: () = thing;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-63593.rs b/src/test/ui/associated-types/issue-63593.rs
new file mode 100644
index 00000000000..8dbc24c0673
--- /dev/null
+++ b/src/test/ui/associated-types/issue-63593.rs
@@ -0,0 +1,13 @@
+#![feature(associated_type_defaults)]
+
+// Tests that `Self` is not assumed to implement `Sized` when used as an
+// associated type default.
+
+trait Inner<S> {}
+
+trait MyTrait {
+    type This = Self;  //~ error: size for values of type `Self` cannot be known
+    fn something<I: Inner<Self::This>>(i: I);
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr
new file mode 100644
index 00000000000..c27800f5a3f
--- /dev/null
+++ b/src/test/ui/associated-types/issue-63593.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-63593.rs:9:5
+   |
+LL | trait MyTrait {
+   | ------------- required by `MyTrait`
+LL |     type This = Self;
+   |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `Self`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs
new file mode 100644
index 00000000000..0ffd6cc2cf2
--- /dev/null
+++ b/src/test/ui/associated-types/issue-65774-1.rs
@@ -0,0 +1,58 @@
+#![feature(associated_type_defaults)]
+
+trait MyDisplay { fn method(&self) { } }
+
+impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
+
+struct T;
+
+trait MPU {
+    type MpuConfig: MyDisplay = T;
+    //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
+}
+
+struct S;
+
+impl MPU for S { }
+//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
+
+trait MyWrite {
+    fn my_write(&self, _: &dyn MyDisplay) { }
+}
+
+trait ProcessType {
+    fn process_detail_fmt(&self, _: &mut dyn MyWrite);
+}
+
+struct Process;
+
+impl ProcessType for Process {
+    fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
+    {
+
+        let mut val: Option<<S as MPU>::MpuConfig> = None;
+        let valref: &mut <S as MPU>::MpuConfig = val.as_mut().unwrap();
+
+        // // This causes a different ICE (but its similar if you squint right):
+        // //
+        // // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
+        //
+        // writer.my_write(valref)
+
+        // This one causes the ICE:
+        // FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
+        // depth=1),Unimplemented)
+        let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+        closure(valref);
+    }
+}
+
+fn create() -> &'static dyn ProcessType {
+    let input: Option<&mut Process> = None;
+    let process: &mut Process = input.unwrap();
+    process
+}
+
+pub fn main() {
+    create();
+}
diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr
new file mode 100644
index 00000000000..559136be705
--- /dev/null
+++ b/src/test/ui/associated-types/issue-65774-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `T: MyDisplay` is not satisfied
+  --> $DIR/issue-65774-1.rs:10:21
+   |
+LL | trait MPU {
+   | --------- required by `MPU`
+LL |     type MpuConfig: MyDisplay = T;
+   |                     ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+
+error[E0277]: the trait bound `T: MyDisplay` is not satisfied
+  --> $DIR/issue-65774-1.rs:16:6
+   |
+LL | impl MPU for S { }
+   |      ^^^ the trait `MyDisplay` is not implemented for `T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs
new file mode 100644
index 00000000000..31e203a81d3
--- /dev/null
+++ b/src/test/ui/associated-types/issue-65774-2.rs
@@ -0,0 +1,58 @@
+#![feature(associated_type_defaults)]
+
+trait MyDisplay { fn method(&self) { } }
+
+impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
+
+struct T;
+
+trait MPU {
+    type MpuConfig: MyDisplay = T;
+    //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
+}
+
+struct S;
+
+impl MPU for S { }
+//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
+
+trait MyWrite {
+    fn my_write(&self, _: &dyn MyDisplay) { }
+}
+
+trait ProcessType {
+    fn process_detail_fmt(&self, _: &mut dyn MyWrite);
+}
+
+struct Process;
+
+impl ProcessType for Process {
+    fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
+    {
+
+        let mut val: Option<<S as MPU>::MpuConfig> = None;
+        let valref: &mut <S as MPU>::MpuConfig = val.as_mut().unwrap();
+
+        // // This causes a different ICE (but its similar if you squint right):
+        // //
+        // // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
+        //
+        writer.my_write(valref)
+
+        // This one causes the ICE:
+        // FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
+        // depth=1),Unimplemented)
+        /*let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+        closure(valref);*/
+    }
+}
+
+fn create() -> &'static dyn ProcessType {
+    let input: Option<&mut Process> = None;
+    let process: &mut Process = input.unwrap();
+    process
+}
+
+pub fn main() {
+    create();
+}
diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr
new file mode 100644
index 00000000000..cb515964226
--- /dev/null
+++ b/src/test/ui/associated-types/issue-65774-2.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `T: MyDisplay` is not satisfied
+  --> $DIR/issue-65774-2.rs:10:21
+   |
+LL | trait MPU {
+   | --------- required by `MPU`
+LL |     type MpuConfig: MyDisplay = T;
+   |                     ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+
+error[E0277]: the trait bound `T: MyDisplay` is not satisfied
+  --> $DIR/issue-65774-2.rs:16:6
+   |
+LL | impl MPU for S { }
+   |      ^^^ the trait `MyDisplay` is not implemented for `T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs
index a2466d28fb0..77f9a3770a3 100644
--- a/src/test/ui/lint/lint-missing-doc.rs
+++ b/src/test/ui/lint/lint-missing-doc.rs
@@ -60,7 +60,7 @@ pub trait D {
 }
 
 /// dox
-pub trait E {
+pub trait E: Sized {
     type AssociatedType; //~ ERROR: missing documentation for an associated type
     type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type
 
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs
index b3d42f09596..03347d5b99a 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.rs
+++ b/src/test/ui/privacy/associated-item-privacy-trait.rs
@@ -23,8 +23,7 @@ mod priv_trait {
         <Pub as PrivTr>::CONST;
         //~^ ERROR associated constant `PrivTr::CONST` is private
         let _: <Pub as PrivTr>::AssocTy;
-        //~^ ERROR trait `priv_trait::PrivTr` is private
-        //~| ERROR trait `priv_trait::PrivTr` is private
+        //~^ ERROR associated type `PrivTr::AssocTy` is private
         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
         //~^ ERROR trait `priv_trait::PrivTr` is private
         pub trait InSignatureTr: PrivTr {}
@@ -116,15 +115,11 @@ mod priv_parent_substs {
         <Priv as PubTr<_>>::CONST;
         //~^ ERROR type `priv_parent_substs::Priv` is private
 
-        let _: <Pub as PubTr>::AssocTy;
-        //~^ ERROR type `priv_parent_substs::Priv` is private
-        //~| ERROR type `priv_parent_substs::Priv` is private
+        let _: <Pub as PubTr>::AssocTy;  // FIXME no longer an error?!
         let _: <Pub as PubTr<_>>::AssocTy;
         //~^ ERROR type `priv_parent_substs::Priv` is private
-        //~| ERROR type `priv_parent_substs::Priv` is private
         let _: <Priv as PubTr<_>>::AssocTy;
         //~^ ERROR type `priv_parent_substs::Priv` is private
-        //~| ERROR type `priv_parent_substs::Priv` is private
 
         pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
         //~^ ERROR type `priv_parent_substs::Priv` is private
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr
index ac422e99855..db24e425a01 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.stderr
+++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr
@@ -42,18 +42,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: trait `priv_trait::PrivTr` is private
-  --> $DIR/associated-item-privacy-trait.rs:25:13
-   |
-LL |         let _: <Pub as PrivTr>::AssocTy;
-   |             ^
-...
-LL |     priv_trait::mac!();
-   |     ------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: trait `priv_trait::PrivTr` is private
+error: associated type `PrivTr::AssocTy` is private
   --> $DIR/associated-item-privacy-trait.rs:25:16
    |
 LL |         let _: <Pub as PrivTr>::AssocTy;
@@ -65,7 +54,7 @@ LL |     priv_trait::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: trait `priv_trait::PrivTr` is private
-  --> $DIR/associated-item-privacy-trait.rs:28:34
+  --> $DIR/associated-item-privacy-trait.rs:27:34
    |
 LL |         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,7 +65,7 @@ LL |     priv_trait::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: trait `priv_trait::PrivTr` is private
-  --> $DIR/associated-item-privacy-trait.rs:30:34
+  --> $DIR/associated-item-privacy-trait.rs:29:34
    |
 LL |         pub trait InSignatureTr: PrivTr {}
    |                                  ^^^^^^
@@ -87,7 +76,7 @@ LL |     priv_trait::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: trait `priv_trait::PrivTr` is private
-  --> $DIR/associated-item-privacy-trait.rs:32:14
+  --> $DIR/associated-item-privacy-trait.rs:31:14
    |
 LL |         impl PrivTr for u8 {}
    |              ^^^^^^
@@ -98,7 +87,7 @@ LL |     priv_trait::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_signature::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:49:21
+  --> $DIR/associated-item-privacy-trait.rs:48:21
    |
 LL |         let value = <Pub as PubTr>::method;
    |                     ^^^^^^^^^^^^^^^^^^^^^^
@@ -109,7 +98,7 @@ LL |     priv_signature::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_signature::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:51:9
+  --> $DIR/associated-item-privacy-trait.rs:50:9
    |
 LL |         value;
    |         ^^^^^
@@ -120,7 +109,7 @@ LL |     priv_signature::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_signature::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:53:13
+  --> $DIR/associated-item-privacy-trait.rs:52:13
    |
 LL |         Pub.method(loop {});
    |             ^^^^^^
@@ -131,7 +120,7 @@ LL |     priv_signature::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:70:21
+  --> $DIR/associated-item-privacy-trait.rs:69:21
    |
 LL |         let value = <Pub as PubTr>::method::<Priv>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -142,7 +131,7 @@ LL |     priv_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:72:9
+  --> $DIR/associated-item-privacy-trait.rs:71:9
    |
 LL |         value;
    |         ^^^^^
@@ -153,7 +142,7 @@ LL |     priv_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:74:9
+  --> $DIR/associated-item-privacy-trait.rs:73:9
    |
 LL |         Pub.method::<Priv>();
    |         ^^^^^^^^^^^^^^^^^^^^
@@ -164,7 +153,7 @@ LL |     priv_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:94:21
+  --> $DIR/associated-item-privacy-trait.rs:93:21
    |
 LL |         let value = <Pub as PubTr>::method;
    |                     ^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +164,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:96:9
+  --> $DIR/associated-item-privacy-trait.rs:95:9
    |
 LL |         value;
    |         ^^^^^
@@ -186,7 +175,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:98:21
+  --> $DIR/associated-item-privacy-trait.rs:97:21
    |
 LL |         let value = <Pub as PubTr<_>>::method;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -197,7 +186,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:100:9
+  --> $DIR/associated-item-privacy-trait.rs:99:9
    |
 LL |         value;
    |         ^^^^^
@@ -208,7 +197,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:102:9
+  --> $DIR/associated-item-privacy-trait.rs:101:9
    |
 LL |         Pub.method();
    |         ^^^^^^^^^^^^
@@ -219,7 +208,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:105:21
+  --> $DIR/associated-item-privacy-trait.rs:104:21
    |
 LL |         let value = <Priv as PubTr<_>>::method;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -230,7 +219,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:107:9
+  --> $DIR/associated-item-privacy-trait.rs:106:9
    |
 LL |         value;
    |         ^^^^^
@@ -241,7 +230,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:109:9
+  --> $DIR/associated-item-privacy-trait.rs:108:9
    |
 LL |         Priv.method();
    |         ^^^^^^^^^^^^^
@@ -252,7 +241,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:112:9
+  --> $DIR/associated-item-privacy-trait.rs:111:9
    |
 LL |         <Pub as PubTr>::CONST;
    |         ^^^^^^^^^^^^^^^^^^^^^
@@ -263,7 +252,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:114:9
+  --> $DIR/associated-item-privacy-trait.rs:113:9
    |
 LL |         <Pub as PubTr<_>>::CONST;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -274,7 +263,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:116:9
+  --> $DIR/associated-item-privacy-trait.rs:115:9
    |
 LL |         <Priv as PubTr<_>>::CONST;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -285,54 +274,10 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:119:13
-   |
-LL |         let _: <Pub as PubTr>::AssocTy;
-   |             ^
-...
-LL |     priv_parent_substs::mac!();
-   |     --------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:119:16
-   |
-LL |         let _: <Pub as PubTr>::AssocTy;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     priv_parent_substs::mac!();
-   |     --------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:122:13
-   |
-LL |         let _: <Pub as PubTr<_>>::AssocTy;
-   |             ^
-...
-LL |     priv_parent_substs::mac!();
-   |     --------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:122:16
+  --> $DIR/associated-item-privacy-trait.rs:119:30
    |
 LL |         let _: <Pub as PubTr<_>>::AssocTy;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     priv_parent_substs::mac!();
-   |     --------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:125:13
-   |
-LL |         let _: <Priv as PubTr<_>>::AssocTy;
-   |             ^
+   |                              ^
 ...
 LL |     priv_parent_substs::mac!();
    |     --------------------------- in this macro invocation
@@ -340,10 +285,10 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:125:16
+  --> $DIR/associated-item-privacy-trait.rs:121:17
    |
 LL |         let _: <Priv as PubTr<_>>::AssocTy;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^
 ...
 LL |     priv_parent_substs::mac!();
    |     --------------------------- in this macro invocation
@@ -351,7 +296,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:129:35
+  --> $DIR/associated-item-privacy-trait.rs:124:35
    |
 LL |         pub type InSignatureTy1 = <Pub as PubTr>::AssocTy;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -362,7 +307,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:131:35
+  --> $DIR/associated-item-privacy-trait.rs:126:35
    |
 LL |         pub type InSignatureTy2 = <Priv as PubTr<Pub>>::AssocTy;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -373,7 +318,7 @@ LL |     priv_parent_substs::mac!();
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: type `priv_parent_substs::Priv` is private
-  --> $DIR/associated-item-privacy-trait.rs:133:14
+  --> $DIR/associated-item-privacy-trait.rs:128:14
    |
 LL |         impl PubTr for u8 {}
    |              ^^^^^
@@ -383,5 +328,5 @@ LL |     priv_parent_substs::mac!();
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 35 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index ad1052ada60..62faae1f399 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -10,6 +10,11 @@ mod m {
     impl PrivTr for Priv {}
     pub trait PubTrAux1<T> {}
     pub trait PubTrAux2 { type A; }
+    impl<T> PubTrAux1<T> for u8 {}
+    impl PubTrAux2 for u8 {
+        type A = Priv;
+        //~^ ERROR private type `m::Priv` in public interface
+    }
 
     // "Private-in-public in associated types is hard error" in RFC 2145
     // applies only to the aliased types, not bounds.
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 3cc551cdede..c57073a004d 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -1,5 +1,14 @@
+error[E0446]: private type `m::Priv` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:15:9
+   |
+LL |     struct Priv;
+   |     - `m::Priv` declared as private
+...
+LL |         type A = Priv;
+   |         ^^^^^^^^^^^^^^ can't leak private type
+
 warning: private trait `m::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-assoc-ty.rs:16:5
+  --> $DIR/private-in-public-assoc-ty.rs:21:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -15,7 +24,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:16:5
+  --> $DIR/private-in-public-assoc-ty.rs:21:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -30,7 +39,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:16:5
+  --> $DIR/private-in-public-assoc-ty.rs:21:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -45,7 +54,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:27:9
+  --> $DIR/private-in-public-assoc-ty.rs:32:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -54,7 +63,7 @@ LL |         type Alias4 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:34:9
+  --> $DIR/private-in-public-assoc-ty.rs:39:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -63,7 +72,7 @@ LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:37:9
+  --> $DIR/private-in-public-assoc-ty.rs:42:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -72,7 +81,7 @@ LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:37:9
+  --> $DIR/private-in-public-assoc-ty.rs:42:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -80,7 +89,7 @@ LL |     trait PrivTr {}
 LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0445, E0446.
 For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index 66d4db3ebaf..e8c767b13e9 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -35,7 +35,7 @@ fn main() {
     <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
     let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
     let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
-    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found
+    <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `u16`
     <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
 
     let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
@@ -52,5 +52,5 @@ fn main() {
     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
     let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
-    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found
+    <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `u16`
 }
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index 60ebe8ee053..e5e6ed9fac9 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -205,19 +205,19 @@ error[E0223]: ambiguous associated type
   --> $DIR/ufcs-partially-resolved.rs:36:12
    |
 LL |     let _: <u8 as Tr>::Y::NN;
-   |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
+   |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u16 as Trait>::NN`
 
-error[E0599]: no associated item named `NN` found for associated type `<u8 as Tr>::Y` in the current scope
+error[E0599]: no associated item named `NN` found for type `u16` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:38:20
    |
 LL |     <u8 as Tr>::Y::NN;
-   |                    ^^ associated item not found in `<u8 as Tr>::Y`
+   |                    ^^ associated item not found in `u16`
 
-error[E0599]: no associated item named `N` found for associated type `<u8 as Dr>::X` in the current scope
+error[E0599]: no associated item named `N` found for type `u16` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:55:20
    |
 LL |     <u8 as Dr>::X::N;
-   |                    ^ associated item not found in `<u8 as Dr>::X`
+   |                    ^ associated item not found in `u16`
 
 error: aborting due to 32 previous errors