Skip to content

Commit cc86c47

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 cc86c47

File tree

3 files changed

+68
-8
lines changed

3 files changed

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

0 commit comments

Comments
 (0)