Skip to content

Commit f6c7504

Browse files
committed
Work around negative_impls that allows unsound overlapping Unpin impls
1 parent 0009800 commit f6c7504

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+308
-120
lines changed

examples/enum-default-expanded.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,15 @@ const _: () = {
7777
__field0: T,
7878
}
7979
impl<'pin, T, U> ::pin_project::__private::Unpin for Enum<T, U> where
80-
__Enum<'pin, T, U>: ::pin_project::__private::Unpin
80+
::pin_project::__private::PinnedFieldsOf<__Enum<'pin, T, U>>:
81+
::pin_project::__private::Unpin
8182
{
8283
}
8384
// A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
8485
#[doc(hidden)]
8586
unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Enum<T, U> where
86-
__Enum<'pin, T, U>: ::pin_project::__private::Unpin
87+
::pin_project::__private::PinnedFieldsOf<__Enum<'pin, T, U>>:
88+
::pin_project::__private::Unpin
8789
{
8890
}
8991

examples/not_unpin-expanded.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ const _: () = {
9595
//
9696
// See https://github.com/taiki-e/pin-project/issues/102#issuecomment-540472282
9797
// for details.
98+
#[doc(hidden)]
9899
impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
99-
::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>:
100-
::pin_project::__private::Unpin
100+
::pin_project::__private::PinnedFieldsOf<
101+
::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>,
102+
>: ::pin_project::__private::Unpin
101103
{
102104
}
103105
// A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
@@ -108,8 +110,9 @@ const _: () = {
108110
// coherence checks are run.
109111
#[doc(hidden)]
110112
unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
111-
::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>:
112-
::pin_project::__private::Unpin
113+
::pin_project::__private::PinnedFieldsOf<
114+
::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>,
115+
>: ::pin_project::__private::Unpin
113116
{
114117
}
115118

examples/pinned_drop-expanded.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,15 @@ const _: () = {
123123
__lifetime0: &'a (),
124124
}
125125
impl<'pin, 'a, T> ::pin_project::__private::Unpin for Struct<'a, T> where
126-
__Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
126+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, 'a, T>>:
127+
::pin_project::__private::Unpin
127128
{
128129
}
129130
// A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
130131
#[doc(hidden)]
131132
unsafe impl<'pin, 'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> where
132-
__Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
133+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, 'a, T>>:
134+
::pin_project::__private::Unpin
133135
{
134136
}
135137
};

examples/project_replace-expanded.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,15 @@ const _: () = {
137137
__field0: T,
138138
}
139139
impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
140-
__Struct<'pin, T, U>: ::pin_project::__private::Unpin
140+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
141+
::pin_project::__private::Unpin
141142
{
142143
}
143144
// A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
144145
#[doc(hidden)]
145146
unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
146-
__Struct<'pin, T, U>: ::pin_project::__private::Unpin
147+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
148+
::pin_project::__private::Unpin
147149
{
148150
}
149151

examples/struct-default-expanded.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ const _: () = {
129129
__field0: T,
130130
}
131131
impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
132-
__Struct<'pin, T, U>: ::pin_project::__private::Unpin
132+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
133+
::pin_project::__private::Unpin
133134
{
134135
}
135136
// A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
@@ -140,7 +141,8 @@ const _: () = {
140141
// coherence checks are run.
141142
#[doc(hidden)]
142143
unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
143-
__Struct<'pin, T, U>: ::pin_project::__private::Unpin
144+
::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
145+
::pin_project::__private::Unpin
144146
{
145147
}
146148

examples/unsafe_unpin-expanded.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ const _: () = {
9292

9393
// Implement `Unpin` via `UnsafeUnpin`.
9494
impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
95-
::pin_project::__private::Wrapper<'pin, Self>: ::pin_project::UnsafeUnpin
95+
::pin_project::__private::PinnedFieldsOf<::pin_project::__private::Wrapper<'pin, Self>>:
96+
::pin_project::UnsafeUnpin
9697
{
9798
}
9899

pin-project-internal/src/pin_project/derive.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,9 @@ fn make_unpin_impl(cx: &Context<'_>) -> TokenStream {
693693

694694
// Make the error message highlight `UnsafeUnpin` argument.
695695
proj_generics.make_where_clause().predicates.push(parse_quote_spanned! { span =>
696-
_pin_project::__private::Wrapper<#lifetime, Self>: _pin_project::UnsafeUnpin
696+
::pin_project::__private::PinnedFieldsOf<
697+
_pin_project::__private::Wrapper<#lifetime, Self>
698+
>: _pin_project::UnsafeUnpin
697699
});
698700

699701
let (impl_generics, _, where_clause) = proj_generics.split_for_impl();
@@ -712,9 +714,9 @@ fn make_unpin_impl(cx: &Context<'_>) -> TokenStream {
712714
let lifetime = &cx.proj.lifetime;
713715

714716
proj_generics.make_where_clause().predicates.push(parse_quote! {
715-
_pin_project::__private::Wrapper<
717+
::pin_project::__private::PinnedFieldsOf<_pin_project::__private::Wrapper<
716718
#lifetime, _pin_project::__private::PhantomPinned
717-
>: _pin_project::__private::Unpin
719+
>>: _pin_project::__private::Unpin
718720
});
719721

720722
let (proj_impl_generics, _, proj_where_clause) = proj_generics.split_for_impl();
@@ -793,7 +795,8 @@ fn make_unpin_impl(cx: &Context<'_>) -> TokenStream {
793795
let (_, ty_generics, where_clause) = cx.orig.generics.split_for_impl();
794796

795797
full_where_clause.predicates.push(parse_quote! {
796-
#struct_ident #proj_ty_generics: _pin_project::__private::Unpin
798+
::pin_project::__private::PinnedFieldsOf<#struct_ident #proj_ty_generics>:
799+
_pin_project::__private::Unpin
797800
});
798801

799802
quote! {

src/lib.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -276,29 +276,42 @@ pub mod __private {
276276
#[doc(hidden)]
277277
#[allow(dead_code)]
278278
pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T);
279-
280279
// SAFETY: `T` implements UnsafeUnpin.
281280
unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {}
282281

282+
// Workaround for issue on unstable negative_impls feature that allows unsound overlapping Unpin
283+
// implementations and rustc bug that leaks unstable negative_impls into stable.
284+
// See https://github.com/taiki-e/pin-project/issues/340#issuecomment-2432146009 for details.
285+
#[doc(hidden)]
286+
pub type PinnedFieldsOf<T> =
287+
<PinnedFieldsOfHelperStruct<T> as PinnedFieldsOfHelperTrait>::Actual;
288+
// We cannot use <Option<T> as IntoIterator>::Item or similar since we should allow ?Sized in T.
289+
#[doc(hidden)]
290+
pub trait PinnedFieldsOfHelperTrait {
291+
type Actual: ?Sized;
292+
}
293+
#[doc(hidden)]
294+
pub struct PinnedFieldsOfHelperStruct<T: ?Sized>(T);
295+
impl<T: ?Sized> PinnedFieldsOfHelperTrait for PinnedFieldsOfHelperStruct<T> {
296+
type Actual = T;
297+
}
298+
283299
// This is an internal helper struct used by `pin-project-internal`.
284300
//
285301
// See https://github.com/taiki-e/pin-project/pull/53 for more details.
286302
#[doc(hidden)]
287303
pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>);
288-
289304
impl<T> Unpin for AlwaysUnpin<'_, T> {}
290305

291306
// This is an internal helper used to ensure a value is dropped.
292307
#[doc(hidden)]
293308
pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T);
294-
295309
impl<T: ?Sized> UnsafeDropInPlaceGuard<T> {
296310
#[doc(hidden)]
297311
pub unsafe fn new(ptr: *mut T) -> Self {
298312
Self(ptr)
299313
}
300314
}
301-
302315
impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> {
303316
fn drop(&mut self) {
304317
// SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee
@@ -316,14 +329,12 @@ pub mod __private {
316329
target: *mut T,
317330
value: ManuallyDrop<T>,
318331
}
319-
320332
impl<T> UnsafeOverwriteGuard<T> {
321333
#[doc(hidden)]
322334
pub unsafe fn new(target: *mut T, value: T) -> Self {
323335
Self { target, value: ManuallyDrop::new(value) }
324336
}
325337
}
326-
327338
impl<T> Drop for UnsafeOverwriteGuard<T> {
328339
fn drop(&mut self) {
329340
// SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee

tests/expand/default/enum.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,16 @@ const _: () = {
131131
}
132132
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
133133
where
134-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
134+
::pin_project::__private::PinnedFieldsOf<
135+
__Enum<'pin, T, U>,
136+
>: _pin_project::__private::Unpin,
135137
{}
136138
#[doc(hidden)]
137139
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
138140
where
139-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
141+
::pin_project::__private::PinnedFieldsOf<
142+
__Enum<'pin, T, U>,
143+
>: _pin_project::__private::Unpin,
140144
{}
141145
trait EnumMustNotImplDrop {}
142146
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/default/struct.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,16 @@ const _: () = {
9090
}
9191
impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
9292
where
93-
__Struct<'pin, T, U>: _pin_project::__private::Unpin,
93+
::pin_project::__private::PinnedFieldsOf<
94+
__Struct<'pin, T, U>,
95+
>: _pin_project::__private::Unpin,
9496
{}
9597
#[doc(hidden)]
9698
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
9799
where
98-
__Struct<'pin, T, U>: _pin_project::__private::Unpin,
100+
::pin_project::__private::PinnedFieldsOf<
101+
__Struct<'pin, T, U>,
102+
>: _pin_project::__private::Unpin,
99103
{}
100104
trait StructMustNotImplDrop {}
101105
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/default/tuple_struct.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,16 @@ const _: () = {
8484
}
8585
impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
8686
where
87-
__TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
87+
::pin_project::__private::PinnedFieldsOf<
88+
__TupleStruct<'pin, T, U>,
89+
>: _pin_project::__private::Unpin,
8890
{}
8991
#[doc(hidden)]
9092
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
9193
where
92-
__TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
94+
::pin_project::__private::PinnedFieldsOf<
95+
__TupleStruct<'pin, T, U>,
96+
>: _pin_project::__private::Unpin,
9397
{}
9498
trait TupleStructMustNotImplDrop {}
9599
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/multifields/enum.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,16 @@ const _: () = {
256256
}
257257
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
258258
where
259-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
259+
::pin_project::__private::PinnedFieldsOf<
260+
__Enum<'pin, T, U>,
261+
>: _pin_project::__private::Unpin,
260262
{}
261263
#[doc(hidden)]
262264
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
263265
where
264-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
266+
::pin_project::__private::PinnedFieldsOf<
267+
__Enum<'pin, T, U>,
268+
>: _pin_project::__private::Unpin,
265269
{}
266270
trait EnumMustNotImplDrop {}
267271
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/multifields/struct.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,16 @@ const _: () = {
143143
}
144144
impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
145145
where
146-
__Struct<'pin, T, U>: _pin_project::__private::Unpin,
146+
::pin_project::__private::PinnedFieldsOf<
147+
__Struct<'pin, T, U>,
148+
>: _pin_project::__private::Unpin,
147149
{}
148150
#[doc(hidden)]
149151
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
150152
where
151-
__Struct<'pin, T, U>: _pin_project::__private::Unpin,
153+
::pin_project::__private::PinnedFieldsOf<
154+
__Struct<'pin, T, U>,
155+
>: _pin_project::__private::Unpin,
152156
{}
153157
trait StructMustNotImplDrop {}
154158
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/multifields/tuple_struct.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,16 @@ const _: () = {
133133
}
134134
impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
135135
where
136-
__TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
136+
::pin_project::__private::PinnedFieldsOf<
137+
__TupleStruct<'pin, T, U>,
138+
>: _pin_project::__private::Unpin,
137139
{}
138140
#[doc(hidden)]
139141
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
140142
where
141-
__TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
143+
::pin_project::__private::PinnedFieldsOf<
144+
__TupleStruct<'pin, T, U>,
145+
>: _pin_project::__private::Unpin,
142146
{}
143147
trait TupleStructMustNotImplDrop {}
144148
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/naming/enum-all.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,16 @@ const _: () = {
192192
}
193193
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
194194
where
195-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
195+
::pin_project::__private::PinnedFieldsOf<
196+
__Enum<'pin, T, U>,
197+
>: _pin_project::__private::Unpin,
196198
{}
197199
#[doc(hidden)]
198200
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
199201
where
200-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
202+
::pin_project::__private::PinnedFieldsOf<
203+
__Enum<'pin, T, U>,
204+
>: _pin_project::__private::Unpin,
201205
{}
202206
trait EnumMustNotImplDrop {}
203207
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/naming/enum-mut.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,16 @@ const _: () = {
8383
}
8484
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
8585
where
86-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
86+
::pin_project::__private::PinnedFieldsOf<
87+
__Enum<'pin, T, U>,
88+
>: _pin_project::__private::Unpin,
8789
{}
8890
#[doc(hidden)]
8991
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
9092
where
91-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
93+
::pin_project::__private::PinnedFieldsOf<
94+
__Enum<'pin, T, U>,
95+
>: _pin_project::__private::Unpin,
9296
{}
9397
trait EnumMustNotImplDrop {}
9498
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/naming/enum-none.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,16 @@ const _: () = {
3838
}
3939
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
4040
where
41-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
41+
::pin_project::__private::PinnedFieldsOf<
42+
__Enum<'pin, T, U>,
43+
>: _pin_project::__private::Unpin,
4244
{}
4345
#[doc(hidden)]
4446
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
4547
where
46-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
48+
::pin_project::__private::PinnedFieldsOf<
49+
__Enum<'pin, T, U>,
50+
>: _pin_project::__private::Unpin,
4751
{}
4852
trait EnumMustNotImplDrop {}
4953
#[allow(clippy::drop_bounds, drop_bounds)]

tests/expand/naming/enum-own.expanded.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,16 @@ const _: () = {
103103
}
104104
impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
105105
where
106-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
106+
::pin_project::__private::PinnedFieldsOf<
107+
__Enum<'pin, T, U>,
108+
>: _pin_project::__private::Unpin,
107109
{}
108110
#[doc(hidden)]
109111
unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
110112
where
111-
__Enum<'pin, T, U>: _pin_project::__private::Unpin,
113+
::pin_project::__private::PinnedFieldsOf<
114+
__Enum<'pin, T, U>,
115+
>: _pin_project::__private::Unpin,
112116
{}
113117
trait EnumMustNotImplDrop {}
114118
#[allow(clippy::drop_bounds, drop_bounds)]

0 commit comments

Comments
 (0)