Skip to content

Commit 8b0f7c0

Browse files
committed
internal: add missing where clause to projection types
`#[pin_data]` failed to propagate the struct's `where` clause to the generated projection struct. As a result, bounds written in a `where` clause could be dropped during expansion, causing type errors when fields depended on those bounds. Fix this by adding the missing `where` clause to the generated projection struct. Add a regression test covering `#[pin_data]` with `where`-clause bounds. Bless expand tests (only `many_generics.rs`) that became outdated. Link: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/generic.20bounds.20and.20.60.23.5Bpin_data.5D.60/with/578381591 Reported-by: Andreas Hindborg <a.hindborg@kernel.org> Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
1 parent bbf992b commit 8b0f7c0

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

internal/src/pin_data.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,9 @@ fn generate_projections(
304304
#[doc = #docs]
305305
#[allow(dead_code)]
306306
#[doc(hidden)]
307-
#vis struct #projection #generics_with_pin_lt {
307+
#vis struct #projection #generics_with_pin_lt
308+
#whr
309+
{
308310
#(#fields_decl)*
309311
___pin_phantom_data: ::core::marker::PhantomData<&'__pin mut ()>,
310312
}

tests/ui/expand/many_generics.expanded.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@ where
1515
/// Pin-projections of [`Foo`]
1616
#[allow(dead_code)]
1717
#[doc(hidden)]
18-
struct FooProjection<
19-
'__pin,
20-
'a,
21-
'b: 'a,
22-
T: Bar<'b> + ?Sized + 'a,
23-
const SIZE: usize = 0,
24-
> {
18+
struct FooProjection<'__pin, 'a, 'b: 'a, T: Bar<'b> + ?Sized + 'a, const SIZE: usize = 0>
19+
where
20+
T: Bar<'a, 1>,
21+
{
2522
array: &'__pin mut [u8; 1024 * 1024],
2623
r: &'__pin mut &'b mut [&'a mut T; SIZE],
2724
_pin: ::core::pin::Pin<&'__pin mut PhantomPinned>,

tests/where_bounds.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
2+
#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
3+
4+
use core::marker::PhantomData;
5+
use pin_init::*;
6+
7+
struct Queue<T: Iterator<Item = u8> + 'static> {
8+
_marker: PhantomData<T>,
9+
}
10+
11+
impl<T: Iterator<Item = u8> + 'static> Queue<T> {
12+
fn new() -> impl PinInit<Self> {
13+
init!(Self {
14+
_marker: PhantomData,
15+
})
16+
}
17+
}
18+
19+
#[pin_data]
20+
struct InlineBoundHandler<T: Iterator<Item = u8> + 'static> {
21+
#[pin]
22+
queue: Queue<T>,
23+
}
24+
25+
impl<T: Iterator<Item = u8> + 'static> InlineBoundHandler<T> {
26+
fn new() -> impl PinInit<Self> {
27+
pin_init!(Self {
28+
queue <- Queue::new(),
29+
})
30+
}
31+
}
32+
33+
#[pin_data]
34+
struct WhereBoundHandler<T>
35+
where
36+
T: Iterator<Item = u8> + 'static,
37+
{
38+
#[pin]
39+
queue: Queue<T>,
40+
}
41+
42+
impl<T> WhereBoundHandler<T>
43+
where
44+
T: Iterator<Item = u8> + 'static,
45+
{
46+
fn new() -> impl PinInit<Self> {
47+
pin_init!(Self {
48+
queue <- Queue::new(),
49+
})
50+
}
51+
}
52+
53+
#[test]
54+
fn pin_data_preserves_inline_and_where_bounds() {
55+
type Iter = core::iter::Empty<u8>;
56+
57+
stack_pin_init!(let inline = InlineBoundHandler::<Iter>::new());
58+
let inline_proj = inline.as_mut().project();
59+
let _ = inline_proj.queue;
60+
61+
stack_pin_init!(let where_ = WhereBoundHandler::<Iter>::new());
62+
let where_proj = where_.as_mut().project();
63+
let _ = where_proj.queue;
64+
}

0 commit comments

Comments
 (0)