about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-10-24 15:31:38 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-11-21 16:00:31 +0000
commit2752e328c9696aa3f8f61046507392ecdedc6667 (patch)
treedcadf8f99d47b13f43218a114431ab6500ee57e2
parent7fe6f36224e92db6fbde952e0b7e50863161f6ee (diff)
downloadrust-2752e328c9696aa3f8f61046507392ecdedc6667.tar.gz
rust-2752e328c9696aa3f8f61046507392ecdedc6667.zip
Allow opaque types in trait impl headers and rely on coherence to reject unsound cases
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs53
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs6
-rw-r--r--src/test/ui/coherence/coherence-with-closure.rs1
-rw-r--r--src/test/ui/coherence/coherence-with-closure.stderr17
-rw-r--r--src/test/ui/coherence/coherence-with-generator.rs1
-rw-r--r--src/test/ui/coherence/coherence-with-generator.stderr17
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs1
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr14
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs1
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr14
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs2
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr19
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs5
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr49
-rw-r--r--src/test/ui/traits/alias/issue-83613.rs1
-rw-r--r--src/test/ui/traits/alias/issue-83613.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs23
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs21
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs19
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-65384.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-65384.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr10
35 files changed, 224 insertions, 229 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 71c932d747b..d66b6585fb6 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, DelayDm};
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IgnoreRegions;
 use rustc_middle::ty::{
@@ -47,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
     let sp = tcx.def_span(def_id);
     let tr = impl_.of_trait.as_ref().unwrap();
 
-    // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
-    // and #84660 where it would otherwise allow unsoundness.
-    if trait_ref.has_opaque_types() {
-        trace!("{:#?}", item);
-        // First we find the opaque type in question.
-        for ty in trait_ref.substs {
-            for ty in ty.walk() {
-                let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
-                let ty::Opaque(def_id, _) = *ty.kind() else { continue };
-                trace!(?def_id);
-
-                // Then we search for mentions of the opaque type's type alias in the HIR
-                struct SpanFinder<'tcx> {
-                    sp: Span,
-                    def_id: DefId,
-                    tcx: TyCtxt<'tcx>,
-                }
-                impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
-                    #[instrument(level = "trace", skip(self, _id))]
-                    fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
-                        // You can't mention an opaque type directly, so we look for type aliases
-                        if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
-                            // And check if that type alias's type contains the opaque type we're looking for
-                            for arg in self.tcx.type_of(def_id).walk() {
-                                if let GenericArgKind::Type(ty) = arg.unpack() {
-                                    if let ty::Opaque(def_id, _) = *ty.kind() {
-                                        if def_id == self.def_id {
-                                            // Finally we update the span to the mention of the type alias
-                                            self.sp = path.span;
-                                            return;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        hir::intravisit::walk_path(self, path)
-                    }
-                }
-
-                let mut visitor = SpanFinder { sp, def_id, tcx };
-                hir::intravisit::walk_item(&mut visitor, item);
-                let reported = tcx
-                    .sess
-                    .struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
-                    .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
-                    .emit();
-                return Err(reported);
-            }
-        }
-        span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
-    }
-
     match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
         Ok(()) => {}
         Err(err) => emit_orphan_check_error(
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 3be0bc4defc..1ee4985cf8d 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -42,7 +42,6 @@ where
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
     GeneratorWitnessSimplifiedType(usize),
-    OpaqueSimplifiedType(D),
     FunctionSimplifiedType(usize),
     PlaceholderSimplifiedType,
 }
@@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>(
             TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
             TreatParams::AsInfer => None,
         },
-        ty::Projection(_) => match treat_params {
+        ty::Opaque(..) | ty::Projection(_) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             //
@@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>(
             }
             TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
         },
-        ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
         ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
         ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
     }
@@ -151,8 +149,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
             | ForeignSimplifiedType(d)
             | TraitSimplifiedType(d)
             | ClosureSimplifiedType(d)
-            | GeneratorSimplifiedType(d)
-            | OpaqueSimplifiedType(d) => Some(d),
+            | GeneratorSimplifiedType(d) => Some(d),
             _ => None,
         }
     }
@@ -182,7 +179,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
             GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
-            OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
             FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
             PlaceholderSimplifiedType => PlaceholderSimplifiedType,
         }
@@ -229,7 +225,7 @@ impl DeepRejectCtxt {
         match impl_ty.kind() {
             // Start by checking whether the type in the impl may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
+            ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -247,8 +243,7 @@ impl DeepRejectCtxt {
             | ty::Never
             | ty::Tuple(..)
             | ty::FnPtr(..)
-            | ty::Foreign(..)
-            | ty::Opaque(..) => {}
+            | ty::Foreign(..) => {}
             ty::FnDef(..)
             | ty::Closure(..)
             | ty::Generator(..)
@@ -328,10 +323,7 @@ impl DeepRejectCtxt {
                 _ => false,
             },
 
-            // Opaque types in impls should be forbidden, but that doesn't
-            // stop compilation. So this match arm should never return true
-            // if compilation succeeds.
-            ty::Opaque(..) => matches!(k, ty::Opaque(..)),
+            ty::Opaque(..) => true,
 
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 3cf2959a9ff..ff013b761e3 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::CRATE_HIR_ID;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@@ -94,7 +94,7 @@ pub fn overlapping_impls<'tcx>(
         return None;
     }
 
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
     let selcx = &mut SelectionContext::intercrate(&infcx);
     let overlaps =
         overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
@@ -105,7 +105,7 @@ pub fn overlapping_impls<'tcx>(
     // In the case where we detect an error, run the check again, but
     // this time tracking intercrate ambiguity causes for better
     // diagnostics. (These take time and can lead to false errors.)
-    let infcx = tcx.infer_ctxt().build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
     let selcx = &mut SelectionContext::intercrate(&infcx);
     selcx.enable_tracking_intercrate_ambiguity_causes();
     Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
diff --git a/src/test/ui/coherence/coherence-with-closure.rs b/src/test/ui/coherence/coherence-with-closure.rs
index 6e3281d8508..5b6a62b24d4 100644
--- a/src/test/ui/coherence/coherence-with-closure.rs
+++ b/src/test/ui/coherence/coherence-with-closure.rs
@@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure {
 struct Wrapper<T>(T);
 trait Trait {}
 impl Trait for Wrapper<OpaqueClosure> {}
-//~^ ERROR cannot implement trait on type alias impl trait
 impl<T: Sync> Trait for Wrapper<T> {}
 //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
 
diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr
index d2ca63fa146..431108e14d7 100644
--- a/src/test/ui/coherence/coherence-with-closure.stderr
+++ b/src/test/ui/coherence/coherence-with-closure.stderr
@@ -1,24 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
-  --> $DIR/coherence-with-closure.rs:12:1
+  --> $DIR/coherence-with-closure.rs:11:1
    |
 LL | impl Trait for Wrapper<OpaqueClosure> {}
    | ------------------------------------- first implementation here
-LL |
 LL | impl<T: Sync> Trait for Wrapper<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence-with-closure.rs:10:24
-   |
-LL | impl Trait for Wrapper<OpaqueClosure> {}
-   |                        ^^^^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/coherence-with-closure.rs:3:22
-   |
-LL | type OpaqueClosure = impl Sized;
-   |                      ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-with-generator.rs b/src/test/ui/coherence/coherence-with-generator.rs
index d34c391db9f..70665ba06f9 100644
--- a/src/test/ui/coherence/coherence-with-generator.rs
+++ b/src/test/ui/coherence/coherence-with-generator.rs
@@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator {
 struct Wrapper<T>(T);
 trait Trait {}
 impl Trait for Wrapper<OpaqueGenerator> {}
-//~^ ERROR cannot implement trait on type alias impl trait
 impl<T: Sync> Trait for Wrapper<T> {}
 //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
 
diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr
index 804bc1c3a6d..6d3be2e16c6 100644
--- a/src/test/ui/coherence/coherence-with-generator.stderr
+++ b/src/test/ui/coherence/coherence-with-generator.stderr
@@ -1,24 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
-  --> $DIR/coherence-with-generator.rs:16:1
+  --> $DIR/coherence-with-generator.rs:15:1
    |
 LL | impl Trait for Wrapper<OpaqueGenerator> {}
    | --------------------------------------- first implementation here
-LL |
 LL | impl<T: Sync> Trait for Wrapper<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence-with-generator.rs:14:24
-   |
-LL | impl Trait for Wrapper<OpaqueGenerator> {}
-   |                        ^^^^^^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/coherence-with-generator.rs:3:24
-   |
-LL | type OpaqueGenerator = impl Sized;
-   |                        ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
index afa95645a27..35994e4a5ba 100644
--- a/src/test/ui/impl-trait/auto-trait.rs
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -20,7 +20,6 @@ impl<T: Send> AnotherTrait for T {}
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
     //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-    //~| ERROR cannot implement trait on type alias impl trait
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 5e10272b0db..81009413c9a 100644
--- a/src/test/ui/impl-trait/auto-trait.stderr
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -7,18 +7,6 @@ LL | impl<T: Send> AnotherTrait for T {}
 LL | impl AnotherTrait for D<OpaqueType> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/auto-trait.rs:21:25
-   |
-LL | impl AnotherTrait for D<OpaqueType> {
-   |                         ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/auto-trait.rs:7:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
index da69bb349ae..70e24a3a9d0 100644
--- a/src/test/ui/impl-trait/negative-reasoning.rs
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -18,7 +18,6 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
     //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-    //~| ERROR cannot implement trait on type alias impl trait
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index 479b451855d..6b8cc9e7374 100644
--- a/src/test/ui/impl-trait/negative-reasoning.stderr
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -9,18 +9,6 @@ LL | impl AnotherTrait for D<OpaqueType> {
    |
    = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/negative-reasoning.rs:19:25
-   |
-LL | impl AnotherTrait for D<OpaqueType> {
-   |                         ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/negative-reasoning.rs:7:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
index 621c4ea6e0d..af9dfe25bb4 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -5,13 +5,13 @@ type Foo = impl PartialEq<(Foo, i32)>;
 struct Bar;
 
 impl PartialEq<(Foo, i32)> for Bar {
-//~^ ERROR cannot implement trait on type alias impl trait
     fn eq(&self, _other: &(Foo, i32)) -> bool {
         true
     }
 }
 
 fn foo() -> Foo {
+    //~^ ERROR can't compare `Bar` with `(Bar, i32)`
     Bar
 }
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
index 2ef1697ba34..7b63a3d0b9f 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
@@ -1,14 +1,15 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:17
+error[E0277]: can't compare `Bar` with `(Bar, i32)`
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13
    |
-LL | impl PartialEq<(Foo, i32)> for Bar {
-   |                 ^^^
+LL | fn foo() -> Foo {
+   |             ^^^ no implementation for `Bar == (Bar, i32)`
+LL |
+LL |     Bar
+   |     --- return type was inferred to be `Bar` here
    |
-note: type alias impl trait defined here
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
-   |
-LL | type Foo = impl PartialEq<(Foo, i32)>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
+   = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
index df7966f00e1..91f1ed48133 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -2,11 +2,13 @@
 
 mod a {
     type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR: unconstrained opaque type
 
     struct Bar;
 
     impl PartialEq<(Bar, i32)> for Bar {
         fn eq(&self, _other: &(Foo, i32)) -> bool {
+            //~^ ERROR: `eq` has an incompatible type for trait
             true
         }
     }
@@ -14,12 +16,13 @@ mod a {
 
 mod b {
     type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR: unconstrained opaque type
 
     struct Bar;
 
     impl PartialEq<(Foo, i32)> for Bar {
-        //~^ ERROR cannot implement trait on type alias impl trait
         fn eq(&self, _other: &(Bar, i32)) -> bool {
+            //~^ ERROR: `eq` has an incompatible type for trait
             true
         }
     }
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 6cd63dcf81c..3dda5761ada 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -1,14 +1,49 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:21
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
    |
-LL |     impl PartialEq<(Foo, i32)> for Bar {
-   |                     ^^^
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error[E0053]: method `eq` has an incompatible type for trait
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                -------------------------- the found opaque type
+...
+LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
+   |                              ^^^^^^^^^^^
+   |                              |
+   |                              expected struct `a::Bar`, found opaque type
+   |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
-note: type alias impl trait defined here
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
+   = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
+              found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _`
+
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error[E0053]: method `eq` has an incompatible type for trait
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                -------------------------- the expected opaque type
+...
+LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
+   |                              ^^^^^^^^^^^
+   |                              |
+   |                              expected opaque type, found struct `b::Bar`
+   |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
+   |
+   = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
+              found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _`
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs
index 04320e72076..2462e703a71 100644
--- a/src/test/ui/traits/alias/issue-83613.rs
+++ b/src/test/ui/traits/alias/issue-83613.rs
@@ -9,5 +9,4 @@ trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
 //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
-//~| ERROR cannot implement trait on type alias impl trait
 fn main() {}
diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr
index b9d93160192..a78294da6c1 100644
--- a/src/test/ui/traits/alias/issue-83613.stderr
+++ b/src/test/ui/traits/alias/issue-83613.stderr
@@ -6,18 +6,6 @@ LL | impl<T: Send> AnotherTrait for T {}
 LL | impl AnotherTrait for OpaqueType {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
 
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-83613.rs:10:23
-   |
-LL | impl AnotherTrait for OpaqueType {}
-   |                       ^^^^^^^^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-83613.rs:4:19
-   |
-LL | type OpaqueType = impl OpaqueTrait;
-   |                   ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/coherence.rs b/src/test/ui/type-alias-impl-trait/coherence.rs
index 98ac215ad6c..077a31494a9 100644
--- a/src/test/ui/type-alias-impl-trait/coherence.rs
+++ b/src/test/ui/type-alias-impl-trait/coherence.rs
@@ -12,6 +12,6 @@ fn use_alias<T>(val: T) -> AliasOfForeignType<T> {
 }
 
 impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
-//~^ ERROR cannot implement trait on type alias impl trait
+//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr
index 3ce25d94f6e..c923eb08ab3 100644
--- a/src/test/ui/type-alias-impl-trait/coherence.stderr
+++ b/src/test/ui/type-alias-impl-trait/coherence.stderr
@@ -1,14 +1,14 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/coherence.rs:14:41
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence.rs:14:1
    |
 LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
-   |                                         ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
+   | |                                       |
+   | |                                       `AliasOfForeignType<T>` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
    |
-note: type alias impl trait defined here
-  --> $DIR/coherence.rs:9:30
-   |
-LL | type AliasOfForeignType<T> = impl LocalTrait;
-   |                              ^^^^^^^^^^^^^^^
+   = note: define and implement a trait or new type instead
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
new file mode 100644
index 00000000000..0efbd1c2bd5
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+trait Foo {
+    type Assoc;
+}
+
+impl Foo for i32 {
+    type Assoc = u32;
+}
+type ImplTrait = impl Sized;
+fn constrain() -> ImplTrait {
+    1u64
+}
+impl Foo for i64 {
+    type Assoc = ImplTrait;
+}
+
+trait Bar<T> {}
+
+impl<T: Foo> Bar<<T as Foo>::Assoc> for T {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
new file mode 100644
index 00000000000..9f32c5d888b
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
@@ -0,0 +1,21 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+type Alias = impl Sized;
+
+fn constrain() -> Alias {
+    1i32
+}
+
+trait HideIt {
+    type Assoc;
+}
+
+impl HideIt for () {
+    type Assoc = Alias;
+}
+
+pub trait Yay {}
+
+impl Yay for <() as HideIt>::Assoc {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
new file mode 100644
index 00000000000..8ec20acef4d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+pub trait Yay { }
+impl Yay for Foo { }
+
+fn foo() {
+    is_yay::<u32>();   //~ ERROR: the trait bound `u32: Yay` is not satisfied
+    is_debug::<u32>(); // OK
+    is_yay::<Foo>();   // OK
+    is_debug::<Foo>(); // OK
+}
+
+fn is_yay<T: Yay>() { }
+fn is_debug<T: Debug>() { }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
new file mode 100644
index 00000000000..1c83105a18a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `u32: Yay` is not satisfied
+  --> $DIR/impl_trait_for_tait_bound.rs:10:14
+   |
+LL |     is_yay::<u32>();
+   |              ^^^ the trait `Yay` is not implemented for `u32`
+   |
+   = help: the trait `Yay` is implemented for `Foo`
+note: required by a bound in `is_yay`
+  --> $DIR/impl_trait_for_tait_bound.rs:16:14
+   |
+LL | fn is_yay<T: Yay>() { }
+   |              ^^^ required by this bound in `is_yay`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
new file mode 100644
index 00000000000..a4b8c2d190d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+
+pub trait Yay { }
+impl Yay for u32 { }
+
+fn foo() {
+    is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
+}
+
+fn is_yay<T: Yay>() { }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
new file mode 100644
index 00000000000..a6440f02c27
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `Foo: Yay` is not satisfied
+  --> $DIR/impl_trait_for_tait_bound2.rs:11:14
+   |
+LL |     is_yay::<Foo>();
+   |              ^^^ the trait `Yay` is not implemented for `Foo`
+   |
+   = help: the trait `Yay` is implemented for `u32`
+note: required by a bound in `is_yay`
+  --> $DIR/impl_trait_for_tait_bound2.rs:14:14
+   |
+LL | fn is_yay<T: Yay>() { }
+   |              ^^^ required by this bound in `is_yay`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs
index 9a119c4d2e0..9a9b2269f80 100644
--- a/src/test/ui/type-alias-impl-trait/issue-65384.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-65384.rs
@@ -8,7 +8,7 @@ impl MyTrait for () {}
 type Bar = impl MyTrait;
 
 impl MyTrait for Bar {}
-//~^ ERROR: cannot implement trait on type alias impl trait
+//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()`
 
 fn bazr() -> Bar { }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr
index 41bcea27e1f..f6692ae3207 100644
--- a/src/test/ui/type-alias-impl-trait/issue-65384.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-65384.stderr
@@ -1,14 +1,12 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-65384.rs:10:18
+error[E0119]: conflicting implementations of trait `MyTrait` for type `()`
+  --> $DIR/issue-65384.rs:10:1
    |
+LL | impl MyTrait for () {}
+   | ------------------- first implementation here
+...
 LL | impl MyTrait for Bar {}
-   |                  ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-65384.rs:8:12
-   |
-LL | type Bar = impl MyTrait;
-   |            ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
index fb56cc54d63..b97e444c6d0 100644
--- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
@@ -1,6 +1,8 @@
 // Regression test for issue #76202
 // Tests that we don't ICE when we have a trait impl on a TAIT.
 
+// check-pass
+
 #![feature(type_alias_impl_trait)]
 
 trait Dummy {}
@@ -14,7 +16,12 @@ trait Test {
 }
 
 impl Test for F {
-    //~^ ERROR cannot implement trait
+    fn test(self) {}
+}
+
+// Ok because `i32` does not implement `Dummy`,
+// so it can't possibly be the hidden type of `F`.
+impl Test for i32 {
     fn test(self) {}
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr
deleted file mode 100644
index 2d4a6854a92..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-76202-trait-impl-for-tait.rs:16:15
-   |
-LL | impl Test for F {
-   |               ^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-76202-trait-impl-for-tait.rs:9:10
-   |
-LL | type F = impl Dummy;
-   |          ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
index fa25d8f762e..2ba4befea2a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
@@ -1,6 +1,8 @@
 // Regression test for issues #84660 and #86411: both are variations on #76202.
 // Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header.
 
+// check-pass
+
 #![feature(type_alias_impl_trait)]
 
 trait Foo {}
@@ -12,7 +14,7 @@ trait TraitArg<T> {
     fn f();
 }
 
-impl TraitArg<Bar> for () { //~ ERROR cannot implement trait
+impl TraitArg<Bar> for () {
     fn f() {
         println!("ho");
     }
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr
deleted file mode 100644
index bb70d07be59..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-84660-trait-impl-for-tait.rs:15:15
-   |
-LL | impl TraitArg<Bar> for () {
-   |               ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-84660-trait-impl-for-tait.rs:8:12
-   |
-LL | type Bar = impl Foo;
-   |            ^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index f12d1b6d953..48d4b0c96ff 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -13,14 +13,14 @@ trait Trait<T, In> {
     fn convert(i: In) -> Self::Out;
 }
 
-impl<In, Out> Trait<Bar, In> for Out { //~ ERROR cannot implement trait
+impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     fn convert(_i: In) -> Self::Out {
         unreachable!();
     }
 }
 
-impl<In, Out> Trait<(), In> for Out {
+impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
     type Out = In;
     fn convert(i: In) -> Self::Out {
         i
diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
index f2d600fb46c..6a75e1bd2c0 100644
--- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
@@ -1,14 +1,12 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-84660-unsoundness.rs:16:21
+error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
+  --> $DIR/issue-84660-unsoundness.rs:23:1
    |
 LL | impl<In, Out> Trait<Bar, In> for Out {
-   |                     ^^^
-   |
-note: type alias impl trait defined here
-  --> $DIR/issue-84660-unsoundness.rs:8:12
-   |
-LL | type Bar = impl Foo;
-   |            ^^^^^^^^
+   | ------------------------------------ first implementation here
+...
+LL | impl<In, Out> Trait<(), In> for Out {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
index ebf3a99bbf9..b0ebdd1bfab 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
@@ -4,11 +4,11 @@
 use std::fmt::Debug;
 
 type FooX = impl Debug;
+//~^ ERROR unconstrained opaque type
 
 trait Foo<A> { }
 
 impl Foo<FooX> for () { }
-//~^ cannot implement trait on type alias impl trait
 
 fn foo() -> impl Foo<FooX> {
     ()
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
index 4a3fb16733e..b1d947a9ccf 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
@@ -1,14 +1,10 @@
-error: cannot implement trait on type alias impl trait
-  --> $DIR/nested-tait-inference3.rs:10:10
-   |
-LL | impl Foo<FooX> for () { }
-   |          ^^^^
-   |
-note: type alias impl trait defined here
+error: unconstrained opaque type
   --> $DIR/nested-tait-inference3.rs:6:13
    |
 LL | type FooX = impl Debug;
    |             ^^^^^^^^^^
+   |
+   = note: `FooX` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error