diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 65e697c8f3b80..7e95e2b7e88b1 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -714,6 +714,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, @only_local: true, "#![rustc_coinductive] changes a trait to be coinductive, allowing cycles in the trait solver." ), + rustc_attr!( + rustc_no_implicit_negative_coherence, AttributeType::Normal, template!(Word), WarnFollowing, @only_local: false, + "#![rustc_no_implicit_negative_coherence] makes the implementation overlap \ + with other implementations even if where clauses are known to never hold" + ), rustc_attr!( rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true, "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl." diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ea261923c6541..cc174a455c7b9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1383,6 +1383,7 @@ symbols! { rustc_mir, rustc_must_implement_one_of, rustc_never_returns_null_ptr, + rustc_no_implicit_negative_coherence, rustc_nonnull_optimization_guaranteed, rustc_nounwind, rustc_object_lifetime_default, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index acab4498a0985..0ad88a7889fe2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -220,7 +220,10 @@ fn overlap<'tcx>( ), ); - if overlap_mode.use_implicit_negative() { + if overlap_mode.use_implicit_negative() + && !tcx.has_attr(impl1_def_id, sym::rustc_no_implicit_negative_coherence) + && !tcx.has_attr(impl2_def_id, sym::rustc_no_implicit_negative_coherence) + { for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] { if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| { impl_intersection_has_impossible_obligation(selcx, &obligations) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 94c682b615ad4..5de708659c8f1 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -406,7 +406,7 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; #[lang = "pin"] #[fundamental] #[repr(transparent)] -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Pin
{ // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: // - deter downstream users from accessing it (which would be unsound!), @@ -418,6 +418,15 @@ pub struct Pin
{
pub pointer: P,
}
+// N.B. manual implementation exists to add `rustc_no_implicit_negative_coherence`
+#[stable(feature = "pin", since = "1.33.0")]
+#[cfg_attr(not(bootstrap), rustc_no_implicit_negative_coherence)]
+impl {
+ fn clone(&self) -> Self {
+ Pin { pointer: self.pointer.clone() }
+ }
+}
+
// The following implementations aren't derived in order to avoid soundness
// issues. `&self.pointer` should not be accessible to untrusted trait
// implementations.
@@ -967,6 +976,7 @@ impl {
}
#[stable(feature = "pin", since = "1.33.0")]
+#[cfg_attr(not(bootstrap), rustc_no_implicit_negative_coherence)]
impl {
fn deref_mut(&mut self) -> &mut P::Target {
Pin::get_mut(Pin::as_mut(self))
diff --git a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs
index 03602144e5001..7ca85fca9ac23 100644
--- a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs
+++ b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs
@@ -1,6 +1,3 @@
-// check-pass
-// known-bug: #85099
-
// Should fail. Can coerce `Pin