Skip to content

Commit 05d512a

Browse files
committed
Auto merge of rust-lang#116706 - compiler-errors:pin-negate, r=<try>
WIP WIP fix for rust-lang#85099, will write up a description w/ `@lcnr` when I'm at my computer r? lcnr
2 parents 57ef889 + 9cff29e commit 05d512a

File tree

6 files changed

+35
-5
lines changed

6 files changed

+35
-5
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
714714
rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, @only_local: true,
715715
"#![rustc_coinductive] changes a trait to be coinductive, allowing cycles in the trait solver."
716716
),
717+
rustc_attr!(
718+
rustc_no_implicit_negative_coherence, AttributeType::Normal, template!(Word), WarnFollowing, @only_local: false,
719+
"#![rustc_no_implicit_negative_coherence] makes the implementation overlap \
720+
with other implementations even if where clauses are known to never hold"
721+
),
717722
rustc_attr!(
718723
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
719724
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ symbols! {
13831383
rustc_mir,
13841384
rustc_must_implement_one_of,
13851385
rustc_never_returns_null_ptr,
1386+
rustc_no_implicit_negative_coherence,
13861387
rustc_nonnull_optimization_guaranteed,
13871388
rustc_nounwind,
13881389
rustc_object_lifetime_default,

compiler/rustc_trait_selection/src/traits/coherence.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ fn overlap<'tcx>(
220220
),
221221
);
222222

223-
if overlap_mode.use_implicit_negative() {
223+
if overlap_mode.use_implicit_negative()
224+
&& !tcx.has_attr(impl1_def_id, sym::rustc_no_implicit_negative_coherence)
225+
&& !tcx.has_attr(impl2_def_id, sym::rustc_no_implicit_negative_coherence)
226+
{
224227
for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
225228
if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
226229
impl_intersection_has_impossible_obligation(selcx, &obligations)

library/core/src/pin.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
406406
#[lang = "pin"]
407407
#[fundamental]
408408
#[repr(transparent)]
409-
#[derive(Copy, Clone)]
409+
#[derive(Copy)]
410410
pub struct Pin<P> {
411411
// FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
412412
// - deter downstream users from accessing it (which would be unsound!),
@@ -418,6 +418,15 @@ pub struct Pin<P> {
418418
pub pointer: P,
419419
}
420420

421+
// N.B. manual implementation exists to add `rustc_no_implicit_negative_coherence`
422+
#[stable(feature = "pin", since = "1.33.0")]
423+
#[cfg_attr(not(bootstrap), rustc_no_implicit_negative_coherence)]
424+
impl<P: Clone> Clone for Pin<P> {
425+
fn clone(&self) -> Self {
426+
Pin { pointer: self.pointer.clone() }
427+
}
428+
}
429+
421430
// The following implementations aren't derived in order to avoid soundness
422431
// issues. `&self.pointer` should not be accessible to untrusted trait
423432
// implementations.
@@ -967,6 +976,7 @@ impl<P: Deref> Deref for Pin<P> {
967976
}
968977

969978
#[stable(feature = "pin", since = "1.33.0")]
979+
#[cfg_attr(not(bootstrap), rustc_no_implicit_negative_coherence)]
970980
impl<P: DerefMut<Target: Unpin>> DerefMut for Pin<P> {
971981
fn deref_mut(&mut self) -> &mut P::Target {
972982
Pin::get_mut(Pin::as_mut(self))

tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// check-pass
2-
// known-bug: #85099
3-
41
// Should fail. Can coerce `Pin<T>` into `Pin<U>` where
52
// `T: Deref<Target: Unpin>` and `U: Deref<Target: !Unpin>`, using the
63
// `CoerceUnsized` impl on `Pin` and an unorthodox `DerefMut` impl for
@@ -43,6 +40,7 @@ impl<'a, Fut: Future<Output = ()>> SomeTrait<'a, Fut> for Fut {
4340
}
4441

4542
impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> {
43+
//~^ ERROR conflicting implementations of trait `DerefMut` for type `Pin<&dyn SomeTrait<'_, _>>`
4644
fn deref_mut<'c>(
4745
self: &'c mut Pin<&'b dyn SomeTrait<'a, Fut>>,
4846
) -> &'c mut (dyn SomeTrait<'a, Fut> + 'b) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0119]: conflicting implementations of trait `DerefMut` for type `Pin<&dyn SomeTrait<'_, _>>`
2+
--> $DIR/pin-unsound-issue-85099-derefmut.rs:42:1
3+
|
4+
LL | impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: conflicting implementation in crate `core`:
8+
- impl<P> DerefMut for Pin<P>
9+
where P: DerefMut, <P as Deref>::Target: Unpin;
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)