about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_data_structures/src/marker.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/always_applicable.rs (renamed from compiler/rustc_hir_analysis/src/check/dropck.rs)149
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs26
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs2
-rw-r--r--library/core/src/convert/mod.rs1
-rw-r--r--tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs8
-rw-r--r--tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr31
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr20
-rw-r--r--tests/ui/coherence/coherence-orphan.rs5
-rw-r--r--tests/ui/coherence/coherence-overlap-negative-impls.rs4
-rw-r--r--tests/ui/coherence/coherence-overlap-negative-impls.stderr16
-rw-r--r--tests/ui/issues/issue-106755.rs5
-rw-r--r--tests/ui/issues/issue-106755.stderr31
-rw-r--r--tests/ui/specialization/defaultimpl/validation.rs15
-rw-r--r--tests/ui/specialization/defaultimpl/validation.stderr28
-rw-r--r--tests/ui/specialization/specialization-overlap-negative.rs4
-rw-r--r--tests/ui/specialization/specialization-overlap-negative.stderr17
19 files changed, 275 insertions, 107 deletions
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 6ae97222f77..4cacc269709 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -1,3 +1,5 @@
+use std::alloc::Allocator;
+
 #[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
             Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
 // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
@@ -28,8 +30,8 @@ impls_dyn_send_neg!(
     [*const T where T: ?Sized]
     [*mut T where T: ?Sized]
     [std::ptr::NonNull<T> where T: ?Sized]
-    [std::rc::Rc<T> where T: ?Sized]
-    [std::rc::Weak<T> where T: ?Sized]
+    [std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
+    [std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
     [std::sync::MutexGuard<'_, T> where T: ?Sized]
     [std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
     [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
@@ -96,8 +98,8 @@ impls_dyn_sync_neg!(
     [std::cell::RefCell<T> where T: ?Sized]
     [std::cell::UnsafeCell<T> where T: ?Sized]
     [std::ptr::NonNull<T> where T: ?Sized]
-    [std::rc::Rc<T> where T: ?Sized]
-    [std::rc::Weak<T> where T: ?Sized]
+    [std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
+    [std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
     [std::cell::OnceCell<T> where T]
     [std::sync::mpsc::Receiver<T> where T]
     [std::sync::mpsc::Sender<T> where T]
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs
index d7dfe482da4..64377ffa347 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs
@@ -1,8 +1,15 @@
+//! This module contains methods that assist in checking that impls are general
+//! enough, i.e. that they always apply to every valid instantaiton of the ADT
+//! they're implemented for.
+//!
+//! This is necessary for `Drop` and negative impls to be well-formed.
+
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
 use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::span_bug;
 use rustc_middle::ty::util::CheckRegions;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
 use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -27,11 +34,12 @@ use crate::hir::def_id::{DefId, LocalDefId};
 /// 3. Any bounds on the generic parameters must be reflected in the
 ///    struct/enum definition for the nominal type itself (i.e.
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
-///
 pub(crate) fn check_drop_impl(
     tcx: TyCtxt<'_>,
     drop_impl_did: DefId,
 ) -> Result<(), ErrorGuaranteed> {
+    let drop_impl_did = drop_impl_did.expect_local();
+
     match tcx.impl_polarity(drop_impl_did) {
         ty::ImplPolarity::Positive => {}
         ty::ImplPolarity::Negative => {
@@ -45,55 +53,107 @@ pub(crate) fn check_drop_impl(
             }));
         }
     }
-    let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity();
-    match dtor_self_type.kind() {
+
+    tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
+
+    let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
+
+    match dtor_impl_trait_ref.self_ty().kind() {
         ty::Adt(adt_def, adt_to_impl_args) => {
-            ensure_drop_params_and_item_params_correspond(
+            ensure_impl_params_and_item_params_correspond(
                 tcx,
-                drop_impl_did.expect_local(),
+                drop_impl_did,
                 adt_def.did(),
                 adt_to_impl_args,
             )?;
 
-            ensure_drop_predicates_are_implied_by_item_defn(
+            ensure_impl_predicates_are_implied_by_item_defn(
                 tcx,
-                drop_impl_did.expect_local(),
-                adt_def.did().expect_local(),
+                drop_impl_did,
+                adt_def.did(),
                 adt_to_impl_args,
             )
         }
         _ => {
-            // Destructors only work on nominal types. This was
-            // already checked by coherence, but compilation may
-            // not have been terminated.
-            let span = tcx.def_span(drop_impl_did);
-            let reported = tcx.dcx().span_delayed_bug(
-                span,
-                format!("should have been rejected by coherence check: {dtor_self_type}"),
-            );
-            Err(reported)
+            span_bug!(tcx.def_span(drop_impl_did), "incoherent impl of Drop");
         }
     }
 }
 
-fn ensure_drop_params_and_item_params_correspond<'tcx>(
+pub(crate) fn check_negative_auto_trait_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
-    drop_impl_did: LocalDefId,
-    self_type_did: DefId,
+    impl_def_id: LocalDefId,
+    impl_trait_ref: ty::TraitRef<'tcx>,
+    polarity: ty::ImplPolarity,
+) -> Result<(), ErrorGuaranteed> {
+    let ty::ImplPolarity::Negative = polarity else {
+        return Ok(());
+    };
+
+    if !tcx.trait_is_auto(impl_trait_ref.def_id) {
+        return Ok(());
+    }
+
+    if tcx.defaultness(impl_def_id).is_default() {
+        tcx.dcx().span_delayed_bug(tcx.def_span(impl_def_id), "default impl cannot be negative");
+    }
+
+    tcx.ensure_ok().orphan_check_impl(impl_def_id)?;
+
+    match impl_trait_ref.self_ty().kind() {
+        ty::Adt(adt_def, adt_to_impl_args) => {
+            ensure_impl_params_and_item_params_correspond(
+                tcx,
+                impl_def_id,
+                adt_def.did(),
+                adt_to_impl_args,
+            )?;
+
+            ensure_impl_predicates_are_implied_by_item_defn(
+                tcx,
+                impl_def_id,
+                adt_def.did(),
+                adt_to_impl_args,
+            )
+        }
+        _ => {
+            if tcx.features().auto_traits() {
+                // NOTE: We ignore the applicability check for negative auto impls
+                // defined in libcore. In the (almost impossible) future where we
+                // stabilize auto impls, then the proper applicability check MUST
+                // be implemented here to handle non-ADT rigid types.
+                Ok(())
+            } else {
+                span_bug!(tcx.def_span(impl_def_id), "incoherent impl of negative auto trait");
+            }
+        }
+    }
+}
+
+fn ensure_impl_params_and_item_params_correspond<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_def_id: LocalDefId,
+    adt_def_id: DefId,
     adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else {
         return Ok(());
     };
 
-    let drop_impl_span = tcx.def_span(drop_impl_did);
-    let item_span = tcx.def_span(self_type_did);
-    let self_descr = tcx.def_descr(self_type_did);
+    let drop_impl_span = tcx.def_span(impl_def_id);
+    let item_span = tcx.def_span(adt_def_id);
+    let self_descr = tcx.def_descr(adt_def_id);
+    let polarity = match tcx.impl_polarity(impl_def_id) {
+        ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
+        ty::ImplPolarity::Negative => "!",
+    };
+    let trait_name = tcx
+        .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
     let mut err = struct_span_code_err!(
         tcx.dcx(),
         drop_impl_span,
         E0366,
-        "`Drop` impls cannot be specialized"
+        "`{polarity}{trait_name}` impls cannot be specialized",
     );
     match arg {
         ty::util::NotUniqueParam::DuplicateParam(arg) => {
@@ -116,17 +176,22 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
 /// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
 /// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
 /// implied by the ADT being well formed.
-fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
+fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
-    drop_impl_def_id: LocalDefId,
-    adt_def_id: LocalDefId,
+    impl_def_id: LocalDefId,
+    adt_def_id: DefId,
     adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
-    let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
-
+    let impl_span = tcx.def_span(impl_def_id.to_def_id());
+    let trait_name = tcx
+        .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
+    let polarity = match tcx.impl_polarity(impl_def_id) {
+        ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
+        ty::ImplPolarity::Negative => "!",
+    };
     // Take the param-env of the adt and instantiate the args that show up in
     // the implementation's self type. This gives us the assumptions that the
     // self ty of the implementation is allowed to know just from it being a
@@ -145,17 +210,21 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     let adt_env =
         ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
 
-    let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id());
+    let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
     let fresh_adt_ty =
-        tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
+        tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
 
     ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
-        .unwrap();
+        .expect("equating fully generic trait ref should never fail");
 
-    for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) {
-        let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
+    for (clause, span) in tcx.predicates_of(impl_def_id).instantiate(tcx, fresh_impl_args) {
+        let normalize_cause = traits::ObligationCause::misc(span, impl_def_id);
         let pred = ocx.normalize(&normalize_cause, adt_env, clause);
-        let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl);
+        let cause = traits::ObligationCause::new(
+            span,
+            impl_def_id,
+            ObligationCauseCode::AlwaysApplicableImpl,
+        );
         ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
     }
 
@@ -173,13 +242,13 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
             let root_predicate = error.root_obligation.predicate;
             if root_predicates.insert(root_predicate) {
                 let item_span = tcx.def_span(adt_def_id);
-                let self_descr = tcx.def_descr(adt_def_id.to_def_id());
+                let self_descr = tcx.def_descr(adt_def_id);
                 guar = Some(
                     struct_span_code_err!(
                         tcx.dcx(),
                         error.root_obligation.cause.span,
                         E0367,
-                        "`Drop` impl requires `{root_predicate}` \
+                        "`{polarity}{trait_name}` impl requires `{root_predicate}` \
                         but the {self_descr} it is implemented for does not",
                     )
                     .with_span_note(item_span, "the implementor must specify the same requirement")
@@ -190,12 +259,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         return Err(guar.unwrap());
     }
 
-    let errors = ocx.infcx.resolve_regions(adt_def_id, adt_env, []);
+    let errors = ocx.infcx.resolve_regions(impl_def_id, adt_env, []);
     if !errors.is_empty() {
         let mut guar = None;
         for error in errors {
             let item_span = tcx.def_span(adt_def_id);
-            let self_descr = tcx.def_descr(adt_def_id.to_def_id());
+            let self_descr = tcx.def_descr(adt_def_id);
             let outlives = match error {
                 RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
                 RegionResolutionError::GenericBoundFailure(_, generic, r) => {
@@ -212,7 +281,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                     tcx.dcx(),
                     error.origin().span(),
                     E0367,
-                    "`Drop` impl requires `{outlives}` \
+                    "`{polarity}{trait_name}` impl requires `{outlives}` \
                     but the {self_descr} it is implemented for does not",
                 )
                 .with_span_note(item_span, "the implementor must specify the same requirement")
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 1c5455710db..d72d5b4fa19 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -62,9 +62,9 @@ a type parameter).
 
 */
 
+pub mod always_applicable;
 mod check;
 mod compare_impl_item;
-pub mod dropck;
 mod entry;
 pub mod intrinsic;
 pub mod intrinsicck;
@@ -113,11 +113,11 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
-    tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
+    tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
 }
 
 fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
-    tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl)
+    tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
 }
 
 /// Given a `DefId` for an opaque type in return position, find its parent item's return
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 0245d4c9fe4..b5c6c2f3861 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -16,6 +16,7 @@ use rustc_span::{ErrorGuaranteed, sym};
 use rustc_type_ir::elaborate;
 use tracing::debug;
 
+use crate::check::always_applicable;
 use crate::errors;
 
 mod builtin;
@@ -24,11 +25,12 @@ mod inherent_impls_overlap;
 mod orphan;
 mod unsafety;
 
-fn check_impl(
-    tcx: TyCtxt<'_>,
+fn check_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
     impl_def_id: LocalDefId,
-    trait_ref: ty::TraitRef<'_>,
-    trait_def: &ty::TraitDef,
+    trait_ref: ty::TraitRef<'tcx>,
+    trait_def: &'tcx ty::TraitDef,
+    polarity: ty::ImplPolarity,
 ) -> Result<(), ErrorGuaranteed> {
     debug!(
         "(checking implementation) adding impl for trait '{:?}', item '{}'",
@@ -44,6 +46,12 @@ fn check_impl(
 
     enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def)
         .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def))
+        .and(always_applicable::check_negative_auto_trait_impl(
+            tcx,
+            impl_def_id,
+            trait_ref,
+            polarity,
+        ))
 }
 
 fn enforce_trait_manually_implementable(
@@ -154,16 +162,16 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
     let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
 
     for &impl_def_id in impls {
-        let trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
-        let trait_ref = trait_header.trait_ref.instantiate_identity();
+        let impl_header = tcx.impl_trait_header(impl_def_id).unwrap();
+        let trait_ref = impl_header.trait_ref.instantiate_identity();
         let trait_def = tcx.trait_def(trait_ref.def_id);
 
         res = res
-            .and(check_impl(tcx, impl_def_id, trait_ref, trait_def))
+            .and(check_impl(tcx, impl_def_id, trait_ref, trait_def, impl_header.polarity))
             .and(check_object_overlap(tcx, impl_def_id, trait_ref))
-            .and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def))
+            .and(unsafety::check_item(tcx, impl_def_id, impl_header, trait_def))
             .and(tcx.ensure_ok().orphan_check_impl(impl_def_id))
-            .and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
+            .and(builtin::check_trait(tcx, def_id, impl_def_id, impl_header));
     }
 
     res
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index d033ecc75db..af38748d5b2 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -397,9 +397,9 @@ pub enum ObligationCauseCode<'tcx> {
 
     RustCall,
 
-    /// Obligations to prove that a `std::ops::Drop` impl is not stronger than
+    /// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than
     /// the ADT it's being implemented for.
-    DropImpl,
+    AlwaysApplicableImpl,
 
     /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
     ConstParam(Ty<'tcx>),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index b85c18c5312..0178400414c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2695,7 +2695,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             | ObligationCauseCode::LetElse
             | ObligationCauseCode::BinOp { .. }
             | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
-            | ObligationCauseCode::DropImpl
+            | ObligationCauseCode::AlwaysApplicableImpl
             | ObligationCauseCode::ConstParam(_)
             | ObligationCauseCode::ReferenceOutlivesReferent(..)
             | ObligationCauseCode::ObjectTypeBound(..) => {}
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index e468f4f0f7e..43fd54f881d 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -778,7 +778,6 @@ impl<T> From<T> for T {
 ///
 /// [#64715]: https://github.com/rust-lang/rust/issues/64715
 #[stable(feature = "convert_infallible", since = "1.34.0")]
-#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
 #[rustc_reservation_impl = "permitting this impl would forbid us from adding \
                             `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
 impl<T> From<!> for T {
diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs
index 24b87892753..15ca0577e4a 100644
--- a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs
+++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs
@@ -8,10 +8,14 @@ struct TestType<T>(::std::marker::PhantomData<T>);
 
 unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
 
-impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
+impl<T: MyTrait> !Send for TestType<T> {}
+//~^ ERROR found both positive and negative implementation
+//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
 
-unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
+unsafe impl<T: 'static> Send for TestType<T> {}
+//~^ ERROR conflicting implementations
 
 impl !Send for TestType<i32> {}
+//~^ ERROR `!Send` impls cannot be specialized
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
index 2463f38a922..c6aed150201 100644
--- a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
+++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
@@ -8,7 +8,7 @@ LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
-  --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:15:1
    |
 LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
    | ------------------------------------------------------ first implementation here
@@ -16,7 +16,32 @@ LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
 LL | unsafe impl<T: 'static> Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
 
-error: aborting due to 2 previous errors
+error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:9
+   |
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   |         ^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1
+   |
+LL | struct TestType<T>(::std::marker::PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0366]: `!Send` impls cannot be specialized
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:18:1
+   |
+LL | impl !Send for TestType<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `i32` is not a generic parameter
+note: use the same sequence of generic lifetime, type and const parameters as the struct definition
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:7:1
+   |
+LL | struct TestType<T>(::std::marker::PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0119, E0751.
+Some errors have detailed explanations: E0119, E0366, E0367, E0751.
 For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index 77d1bdee5ac..bc81dd6f286 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -1,9 +1,3 @@
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
-   |
-LL | impl !Marker1 for dyn Object + Marker2 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
 error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
    |
@@ -12,11 +6,11 @@ LL | impl !Marker1 for dyn Object + Marker2 {}
    |
    = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
 
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
    |
-LL | impl !Marker2 for dyn Object + Marker2 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+LL | impl !Marker1 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
 
 error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
@@ -26,6 +20,12 @@ LL | impl !Marker2 for dyn Object + Marker2 {}
    |
    = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
 
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
    |
diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs
index aee6647a788..665fa15c56e 100644
--- a/tests/ui/coherence/coherence-orphan.rs
+++ b/tests/ui/coherence/coherence-orphan.rs
@@ -8,12 +8,13 @@ use lib::TheTrait;
 struct TheType;
 
 impl TheTrait<usize> for isize {}
-//~^ ERROR E0117
+//~^ ERROR  only traits defined in the current crate can be implemented for primitive types
 
 impl TheTrait<TheType> for isize {}
 
 impl TheTrait<isize> for TheType {}
 
-impl !Send for Vec<isize> {} //~ ERROR E0117
+impl !Send for Vec<isize> {}
+//~^ ERROR only traits defined in the current crate can be implemented for types defined outside of the crate
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-overlap-negative-impls.rs b/tests/ui/coherence/coherence-overlap-negative-impls.rs
index ffcd56817e5..ba90a37cb2a 100644
--- a/tests/ui/coherence/coherence-overlap-negative-impls.rs
+++ b/tests/ui/coherence/coherence-overlap-negative-impls.rs
@@ -1,6 +1,3 @@
-//@ check-pass
-//@ known-bug: #74629
-
 // Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
 // `T = Test, F = ()`, all bounds are true, making both impls applicable.
 // `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
@@ -39,6 +36,7 @@ mod private {
     pub auto trait NotNil {}
 
     impl !NotNil for Is<Nil> {}
+    //~^ ERROR `!NotNil` impls cannot be specialized
 }
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-overlap-negative-impls.stderr b/tests/ui/coherence/coherence-overlap-negative-impls.stderr
new file mode 100644
index 00000000000..fe22cf61b75
--- /dev/null
+++ b/tests/ui/coherence/coherence-overlap-negative-impls.stderr
@@ -0,0 +1,16 @@
+error[E0366]: `!NotNil` impls cannot be specialized
+  --> $DIR/coherence-overlap-negative-impls.rs:38:5
+   |
+LL |     impl !NotNil for Is<Nil> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Nil` is not a generic parameter
+note: use the same sequence of generic lifetime, type and const parameters as the struct definition
+  --> $DIR/coherence-overlap-negative-impls.rs:35:5
+   |
+LL |     pub struct Is<T>(T);
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0366`.
diff --git a/tests/ui/issues/issue-106755.rs b/tests/ui/issues/issue-106755.rs
index 689b1d885ae..d7e7122ebda 100644
--- a/tests/ui/issues/issue-106755.rs
+++ b/tests/ui/issues/issue-106755.rs
@@ -10,10 +10,13 @@ struct TestType<T>(::std::marker::PhantomData<T>);
 
 unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
 
-impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
+impl<T: MyTrait> !Send for TestType<T> {}
+//~^ ERROR found both positive and negative implementation
+//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
 
 unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
 
 impl !Send for TestType<i32> {}
+//~^ ERROR `!Send` impls cannot be specialized
 
 fn main() {}
diff --git a/tests/ui/issues/issue-106755.stderr b/tests/ui/issues/issue-106755.stderr
index 54397034062..da6b8c5c563 100644
--- a/tests/ui/issues/issue-106755.stderr
+++ b/tests/ui/issues/issue-106755.stderr
@@ -8,7 +8,7 @@ LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
 error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
-  --> $DIR/issue-106755.rs:15:1
+  --> $DIR/issue-106755.rs:17:1
    |
 LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
    | ------------------------------------------------------ first implementation here
@@ -16,7 +16,32 @@ LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
 LL | unsafe impl<T: 'static> Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
 
-error: aborting due to 2 previous errors
+error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
+  --> $DIR/issue-106755.rs:13:9
+   |
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   |         ^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/issue-106755.rs:9:1
+   |
+LL | struct TestType<T>(::std::marker::PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0366]: `!Send` impls cannot be specialized
+  --> $DIR/issue-106755.rs:19:1
+   |
+LL | impl !Send for TestType<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `i32` is not a generic parameter
+note: use the same sequence of generic lifetime, type and const parameters as the struct definition
+  --> $DIR/issue-106755.rs:9:1
+   |
+LL | struct TestType<T>(::std::marker::PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0119, E0751.
+Some errors have detailed explanations: E0119, E0366, E0367, E0751.
 For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs
index 4049c4ea14c..14771be8982 100644
--- a/tests/ui/specialization/defaultimpl/validation.rs
+++ b/tests/ui/specialization/defaultimpl/validation.rs
@@ -6,12 +6,17 @@ struct Z;
 
 default impl S {} //~ ERROR inherent impls cannot be `default`
 
-default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
-//~^ ERROR `S` cannot be sent between threads safely
-default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
-                            //~^ ERROR negative impls cannot be default impls
+default unsafe impl Send for S {}
+//~^ ERROR impls of auto traits cannot be default
+
+default impl !Send for Z {}
+//~^ ERROR impls of auto traits cannot be default
+//~| ERROR negative impls cannot be default impls
+//~| ERROR `!Send` impl requires `Z: Send` but the struct it is implemented for does not
 
 trait Tr {}
-default impl !Tr for S {} //~ ERROR negative impls cannot be default impls
+
+default impl !Tr for S {}
+//~^ ERROR negative impls cannot be default impls
 
 fn main() {}
diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr
index f56f16162a2..d034386b842 100644
--- a/tests/ui/specialization/defaultimpl/validation.stderr
+++ b/tests/ui/specialization/defaultimpl/validation.stderr
@@ -26,22 +26,20 @@ LL | default unsafe impl Send for S {}
    | |
    | default because of this
 
-error[E0277]: `S` cannot be sent between threads safely
-  --> $DIR/validation.rs:9:1
+error[E0367]: `!Send` impl requires `Z: Send` but the struct it is implemented for does not
+  --> $DIR/validation.rs:12:1
    |
-LL | default unsafe impl Send for S {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `S` cannot be sent between threads safely
-   |
-   = help: the trait `Send` is not implemented for `S`
-   = help: the trait `Send` is implemented for `S`
-   = help: see issue #48214
-help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+LL | default impl !Send for Z {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-LL + #![feature(trivial_bounds)]
+note: the implementor must specify the same requirement
+  --> $DIR/validation.rs:5:1
    |
+LL | struct Z;
+   | ^^^^^^^^
 
 error: impls of auto traits cannot be default
-  --> $DIR/validation.rs:11:15
+  --> $DIR/validation.rs:12:15
    |
 LL | default impl !Send for Z {}
    | -------       ^^^^ auto trait
@@ -49,18 +47,18 @@ LL | default impl !Send for Z {}
    | default because of this
 
 error[E0750]: negative impls cannot be default impls
-  --> $DIR/validation.rs:11:1
+  --> $DIR/validation.rs:12:1
    |
 LL | default impl !Send for Z {}
    | ^^^^^^^      ^
 
 error[E0750]: negative impls cannot be default impls
-  --> $DIR/validation.rs:15:1
+  --> $DIR/validation.rs:19:1
    |
 LL | default impl !Tr for S {}
    | ^^^^^^^      ^
 
 error: aborting due to 6 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0277, E0750.
-For more information about an error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0367, E0750.
+For more information about an error, try `rustc --explain E0367`.
diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs
index 550d3708295..244f21c7ba9 100644
--- a/tests/ui/specialization/specialization-overlap-negative.rs
+++ b/tests/ui/specialization/specialization-overlap-negative.rs
@@ -6,6 +6,8 @@ trait MyTrait {}
 struct TestType<T>(::std::marker::PhantomData<T>);
 
 unsafe impl<T: Clone> Send for TestType<T> {}
-impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0751
+impl<T: MyTrait> !Send for TestType<T> {}
+//~^ ERROR found both positive and negative implementation of trait `Send` for type `TestType<_>`
+//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
 
 fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr
index a8e99953e2b..4874e897726 100644
--- a/tests/ui/specialization/specialization-overlap-negative.stderr
+++ b/tests/ui/specialization/specialization-overlap-negative.stderr
@@ -16,6 +16,19 @@ LL | unsafe impl<T: Clone> Send for TestType<T> {}
 LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
+  --> $DIR/specialization-overlap-negative.rs:9:9
+   |
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+   |         ^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/specialization-overlap-negative.rs:6:1
+   |
+LL | struct TestType<T>(::std::marker::PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0751`.
+Some errors have detailed explanations: E0367, E0751.
+For more information about an error, try `rustc --explain E0367`.