From 69118012ad0dc36fe4596c783b74edf6301f71cd Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Wed, 17 Jul 2024 20:01:30 +0200 Subject: [PATCH] Test(ui): Extend block tests for with_encoding Signed-off-by: Paul Mabileau --- .../test-ui/ui/block_lifetimes_independent.rs | 50 ++++++++- .../ui/block_lifetimes_independent.stderr | 104 ++++++++++++++++++ .../ui/lifetime_of_closure_tied_to_block.rs | 30 ++++- .../lifetime_of_closure_tied_to_block.stderr | 59 +++++++++- ...tack_block_with_encoding_requires_clone.rs | 20 ++++ ..._block_with_encoding_requires_clone.stderr | 31 ++++++ 6 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 crates/test-ui/ui/stack_block_with_encoding_requires_clone.rs create mode 100644 crates/test-ui/ui/stack_block_with_encoding_requires_clone.stderr diff --git a/crates/test-ui/ui/block_lifetimes_independent.rs b/crates/test-ui/ui/block_lifetimes_independent.rs index 1f169b6ba..e35a5500d 100644 --- a/crates/test-ui/ui/block_lifetimes_independent.rs +++ b/crates/test-ui/ui/block_lifetimes_independent.rs @@ -1,7 +1,9 @@ //! Test that lifetimes in blocks are not bound to each other. //! //! These tests will succeed if there are `'a: 'b`-like bounds on the closure. -use block2::RcBlock; +use block2::{ManualBlockEncoding, RcBlock}; +use std::ffi::CStr; +use std::marker::PhantomData; fn args<'a, 'b>( f: impl Fn(&'a i32, &'b i32) + 'static, @@ -23,4 +25,50 @@ fn return_entire<'a, 'b>(f: impl Fn() -> &'a i32 + 'b) -> RcBlock &' RcBlock::new(f) } +fn args_with_encoding<'a, 'b>( + f: impl Fn(&'a i32, &'b i32) + 'static, +) -> RcBlock { + struct Enc<'a, 'b>(PhantomData<&'a i32>, PhantomData<&'b i32>); + unsafe impl<'a, 'b> ManualBlockEncoding for Enc<'a, 'b> { + type Arguments = (&'a i32, &'b i32); + type Return = (); + const ENCODING_CSTR: &'static CStr = c"v24@?0^i8^i16"; + } + unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } +} + +fn args_return_with_encoding<'a, 'b>( + f: impl Fn(&'a i32) -> &'b i32 + 'static, +) -> RcBlock &'a i32 + 'static> { + struct Enc<'a, 'b>(PhantomData<&'a i32>, PhantomData<&'b i32>); + unsafe impl<'a, 'b> ManualBlockEncoding for Enc<'a, 'b> { + type Arguments = (&'a i32,); + type Return = &'b i32; + const ENCODING_CSTR: &'static CStr = c"^i816@?0^i8"; + } + unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } +} + +fn args_entire_with_encoding<'a, 'b>(f: impl Fn(&'a i32) + 'b) -> RcBlock { + struct Enc<'a>(PhantomData<&'a i32>); + unsafe impl<'a> ManualBlockEncoding for Enc<'a> { + type Arguments = (&'a i32,); + type Return = (); + const ENCODING_CSTR: &'static CStr = c"v16@?0^i8"; + } + unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } +} + +fn return_entire_with_encoding<'a, 'b>( + f: impl Fn() -> &'a i32 + 'b, +) -> RcBlock &'b i32 + 'a> { + struct Enc<'a>(PhantomData<&'a i32>); + unsafe impl<'a> ManualBlockEncoding for Enc<'a> { + type Arguments = (); + type Return = &'a i32; + const ENCODING_CSTR: &'static CStr = c"^i8@?0"; + } + unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } +} + fn main() {} diff --git a/crates/test-ui/ui/block_lifetimes_independent.stderr b/crates/test-ui/ui/block_lifetimes_independent.stderr index 3ec490778..94aa8f600 100644 --- a/crates/test-ui/ui/block_lifetimes_independent.stderr +++ b/crates/test-ui/ui/block_lifetimes_independent.stderr @@ -99,3 +99,107 @@ error: lifetime may not live long enough | ^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_return_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_return_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a, 'b>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_entire_with_encoding<'a, 'b>(f: impl Fn(&'a i32) + 'b) -> RcBlock { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn args_entire_with_encoding<'a, 'b>(f: impl Fn(&'a i32) + 'b) -> RcBlock { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn return_entire_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> ui/block_lifetimes_independent.rs + | + | fn return_entire_with_encoding<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... + | unsafe { RcBlock::with_encoding::<_, _, _, Enc<'a>>(f) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` diff --git a/crates/test-ui/ui/lifetime_of_closure_tied_to_block.rs b/crates/test-ui/ui/lifetime_of_closure_tied_to_block.rs index b166d6e4a..6da1cfc69 100644 --- a/crates/test-ui/ui/lifetime_of_closure_tied_to_block.rs +++ b/crates/test-ui/ui/lifetime_of_closure_tied_to_block.rs @@ -1,4 +1,12 @@ -use block2::{RcBlock, StackBlock}; +use block2::{ManualBlockEncoding, RcBlock, StackBlock}; +use std::ffi::CStr; + +struct VoidToI32; +unsafe impl ManualBlockEncoding for VoidToI32 { + type Arguments = (); + type Return = i32; + const ENCODING_CSTR: &'static CStr = c"i8@?0"; +} fn main() { let _ = { @@ -11,6 +19,16 @@ fn main() { RcBlock::new(|| x + 2).clone() }; + let _ = { + let x = 2; + unsafe { RcBlock::with_encoding::<_, _, _, VoidToI32>(|| x + 2) } + }; + + let _ = { + let x = 2; + unsafe { RcBlock::with_encoding::<_, _, _, VoidToI32>(|| x + 2).clone() } + }; + let _ = { let x = 2; StackBlock::new(|| x + 2) @@ -20,4 +38,14 @@ fn main() { let x = 2; StackBlock::new(|| x + 2).copy() }; + + let _ = { + let x = 2; + unsafe { StackBlock::with_encoding::(|| x + 2) } + }; + + let _ = { + let x = 2; + unsafe { StackBlock::with_encoding::(|| x + 2).copy() } + }; } diff --git a/crates/test-ui/ui/lifetime_of_closure_tied_to_block.stderr b/crates/test-ui/ui/lifetime_of_closure_tied_to_block.stderr index b6b6c6ec4..02ea98624 100644 --- a/crates/test-ui/ui/lifetime_of_closure_tied_to_block.stderr +++ b/crates/test-ui/ui/lifetime_of_closure_tied_to_block.stderr @@ -28,9 +28,42 @@ error[E0597]: `x` does not live long enough | help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped | -11 | RcBlock::new(|| x + 2).clone(); +19 | RcBlock::new(|| x + 2).clone(); | + +error[E0597]: `x` does not live long enough + --> ui/lifetime_of_closure_tied_to_block.rs + | + | let x = 2; + | - binding `x` declared here + | unsafe { RcBlock::with_encoding::<_, _, _, VoidToI32>(|| x + 2) } + | -- ^ borrowed value does not live long enough + | | + | value captured here + | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> ui/lifetime_of_closure_tied_to_block.rs + | + | let x = 2; + | - binding `x` declared here + | unsafe { RcBlock::with_encoding::<_, _, _, VoidToI32>(|| x + 2).clone() } + | ------------------------------------------------^----- + | | | | + | | | borrowed value does not live long enough + | | value captured here + | a temporary with access to the borrow is created here ... + | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `RcBlock` + | | + | `x` dropped here while still borrowed + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +29 | unsafe { RcBlock::with_encoding::<_, _, _, VoidToI32>(|| x + 2).clone(); } + | + + error[E0597]: `x` does not live long enough --> ui/lifetime_of_closure_tied_to_block.rs | @@ -54,3 +87,27 @@ error[E0597]: `x` does not live long enough | value captured here | }; | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> ui/lifetime_of_closure_tied_to_block.rs + | + | let x = 2; + | - binding `x` declared here + | unsafe { StackBlock::with_encoding::(|| x + 2) } + | -- ^ borrowed value does not live long enough + | | + | value captured here + | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> ui/lifetime_of_closure_tied_to_block.rs + | + | let x = 2; + | - binding `x` declared here + | unsafe { StackBlock::with_encoding::(|| x + 2).copy() } + | -- ^ borrowed value does not live long enough + | | + | value captured here + | }; + | - `x` dropped here while still borrowed diff --git a/crates/test-ui/ui/stack_block_with_encoding_requires_clone.rs b/crates/test-ui/ui/stack_block_with_encoding_requires_clone.rs new file mode 100644 index 000000000..bd122a2eb --- /dev/null +++ b/crates/test-ui/ui/stack_block_with_encoding_requires_clone.rs @@ -0,0 +1,20 @@ +use block2::{ManualBlockEncoding, StackBlock}; +use std::ffi::CStr; + +struct Foo; + +fn main() { + struct FooBlockEncoding; + unsafe impl ManualBlockEncoding for FooBlockEncoding { + type Arguments = (); + type Return = (); + const ENCODING_CSTR: &'static CStr = c"v8@?0"; + } + + let foo = Foo; + let _ = unsafe { + StackBlock::with_encoding::(move || { + let _ = &foo; + }) + }; +} diff --git a/crates/test-ui/ui/stack_block_with_encoding_requires_clone.stderr b/crates/test-ui/ui/stack_block_with_encoding_requires_clone.stderr new file mode 100644 index 000000000..d615bf2cd --- /dev/null +++ b/crates/test-ui/ui/stack_block_with_encoding_requires_clone.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Foo: Clone` is not satisfied in `{closure@$DIR/ui/stack_block_with_encoding_requires_clone.rs:16:55: 16:62}` + --> ui/stack_block_with_encoding_requires_clone.rs + | + | StackBlock::with_encoding::(move || { + | --------------------------------------------- ^------ + | | | + | _________|_____________________________________________within this `{closure@$DIR/ui/stack_block_with_encoding_requires_clone.rs:16:55: 16:62}` + | | | + | | required by a bound introduced by this call + | | let _ = &foo; + | | }) + | |_________^ within `{closure@$DIR/ui/stack_block_with_encoding_requires_clone.rs:16:55: 16:62}`, the trait `Clone` is not implemented for `Foo`, which is required by `{closure@$DIR/ui/stack_block_with_encoding_requires_clone.rs:16:55: 16:62}: Clone` + | +note: required because it's used within this closure + --> ui/stack_block_with_encoding_requires_clone.rs + | + | StackBlock::with_encoding::(move || { + | ^^^^^^^ +note: required by a bound in `StackBlock::<'f, A, R, Closure>::with_encoding` + --> $WORKSPACE/crates/block2/src/stack.rs + | + | Closure: IntoBlock<'f, A, R> + Clone, + | ^^^^^ required by this bound in `StackBlock::<'f, A, R, Closure>::with_encoding` +... + | pub unsafe fn with_encoding(closure: Closure) -> Self + | ------------- required by a bound in this associated function +help: consider annotating `Foo` with `#[derive(Clone)]` + | +4 + #[derive(Clone)] +5 | struct Foo; + |