Rust futures -- use Box::pin or pin_mut outside futures::select - rust

I had read the usage of futures::select, but I encounter an obstacle. here is my confusion: At the part of expression in select!, we should use a type implementing Unpin and FusedFuture, but here Pin on a Unpin is no effect accoring to usage of Pin.
1.why we should wrap Pin on a Unpin if call fuse() outside a select!, if it have no effect 2.why a Pin could be used in expression of select! and pass the checker if there needs a Unpin.
here is code:
async fn async_identity_fn(arg: usize) -> usize {
arg
}
let fut_1 = async_identity_fn(1).fuse();
let fut_2 = async_identity_fn(2).fuse();
let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap
pin_mut!(fut_2); // Pins the Future on the stack
let res = select! {
a_res = fut_1 => a_res,
b_res = fut_2 => b_res,
};
here is some link
usage of Pin ;
confusion about usage of Pin
usage of select!
confusion about condition of using select!

why we should wrap Pin on a Unpin if call fuse() outside a select!, if it have no effect
Because it is not Unpin:
error[E0277]: `from_generator::GenFuture<[static generator#src/lib.rs:3:49: 5:2]>` cannot be unpinned
--> src/lib.rs:12:15
|
12 | let res = select! {
| _______________^
13 | | a_res = fut_1 => a_res,
14 | | b_res = fut_2 => b_res,
15 | | };
| |_____^ within `futures::future::future::fuse::_::__Origin<'_, impl futures::Future<Output = usize>>`, the trait `Unpin` is not implemented for `from_generator::GenFuture<[static generator#src/lib.rs:3:49: 5:2]>`
|
= note: consider using `Box::pin`
= note: required because it appears within the type `impl futures::Future<Output = usize>`
= note: required because it appears within the type `impl futures::Future<Output = usize>`
= note: required because it appears within the type `Option<impl futures::Future<Output = usize>>`
= note: required because it appears within the type `futures::future::future::fuse::_::__Origin<'_, impl futures::Future<Output = usize>>`
= note: required because of the requirements on the impl of `Unpin` for `futures::future::Fuse<impl futures::Future<Output = usize>>`
note: required by a bound in `futures_util::async_await::assert_unpin`
--> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.21/src/async_await/mod.rs:50:24
|
50 | pub fn assert_unpin<T: Unpin>(_: &T) {}
| ^^^^^ required by this bound in `futures_util::async_await::assert_unpin`
= note: this error originates in the macro `$crate::select_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
So it is not valid for select!. However, even for !Unpin value, if we pin it the pinned value does implement Unpin (not because of Pin itself but because Box and references are always Unpin).
why a Pin could be used in expression of select! and pass the checker if there needs a Unpin.
Because the macro can pin the result of the call itself. However, when using variables directly it cannot do that soundly.

Related

implementing obj-rs example to glium

I am trying to load a model into glium, I am using crate obj-rs for this. My model works fine with this example. Unfortunately whenever I try to move code from the example to my project (which is basically code copied from here) I fail with an error:
error[E0277]: the trait bound `glium::Display: glium::backend::Facade` is not satisfied
--> src/main.rs:27:32
|
27 | let vb = obj.vertex_buffer(&display)?;
| ------------- ^^^^^^^^ the trait `glium::backend::Facade` is not implemented for `glium::Display`
| |
| required by a bound introduced by this call
|
= help: the trait `glium::backend::Facade` is implemented for `Rc<glium::context::Context>`
note: required by a bound in `obj::glium_support::<impl Obj<V, I>>::vertex_buffer`
--> /Users/user/project/obj-rs/src/lib.rs:309:33
|
309 | pub fn vertex_buffer<F: Facade>(
| ^^^^^^ required by this bound in `obj::glium_support::<impl Obj<V, I>>::vertex_buffer`
error[E0277]: the trait bound `glium::Display: glium::backend::Facade` is not satisfied
--> src/main.rs:28:31
|
28 | let ib = obj.index_buffer(&display)?;
| ------------ ^^^^^^^^ the trait `glium::backend::Facade` is not implemented for `glium::Display`
| |
| required by a bound introduced by this call
|
= help: the trait `glium::backend::Facade` is implemented for `Rc<glium::context::Context>`
note: required by a bound in `obj::glium_support::<impl Obj<V, I>>::index_buffer`
--> /Users/user/project/obj-rs/src/lib.rs:317:32
|
317 | pub fn index_buffer<F: Facade>(
| ^^^^^^ required by this bound in `obj::glium_support::<impl Obj<V, I>>::index_buffer`
I am new to rust so most of the time I don't know what I am doing. I find it really hard to simply make copied code work. I tried implementing Facade for Display but that didn't seem to make any difference, just more errors. Could you tell me what's wrong, or at least provide me with an example that works, I just want to add my own models to glium examples.
Here are the parts of code that I changed:
fn main() -> Result<(), Box<dyn std::error::Error>>{
#[allow(unused_imports)]
use glium::{glutin, Surface};
use obj::{load_obj, Obj};
use glium::glutin::dpi::LogicalSize;
let event_loop = glutin::event_loop::EventLoop::new();
let window = glutin::window::WindowBuilder::new()
.with_inner_size(LogicalSize::new(500.0, 400.0))
.with_title("obj-rs");
let context = glutin::ContextBuilder::new().with_depth_buffer(24);
let display = glium::Display::new(window, context, &event_loop)?;
let input = include_bytes!("model.obj");
let obj: Obj = load_obj(&input[..])?;
//two lines causing the problem
//let vb = obj.vertex_buffer(&display)?;
//let ib = obj.index_buffer(&display)?;
let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap();
..... rest is the same as in the glium example
One thing that I would like to differ from obj-rs example is not to use local source if you know what I mean. Basically something like this:
[dependencies]
glium = "*"
obj-rs = { version = "*", features = ["glium"] }

Why does &i32 sometimes implement Unpin and sometimes not?

use std::pin::Pin;
fn main() {
let val: i32 = 3;
let val_pin = Pin::new(&val);
f(val_pin);
f(Pin::new(&val));
}
fn f(_val: Pin<&dyn TestTrait>) {}
trait TestTrait {}
impl TestTrait for i32 {}
Line 9 f(Pin::new(&val)); throws a compiler error, but line 6 let val_pin = Pin::new(&val); does not. The compiler error is:
error[E0277]: `dyn TestTrait` cannot be unpinned
--> src/main.rs:9:7
|
9 | f(Pin::new(&val));
| ^^^^^^^^ the trait `Unpin` is not implemented for `dyn TestTrait`
|
= note: consider using `Box::pin`
note: required by a bound in `Pin::<P>::new`
--> /usr/lib/rustlib/src/rust/library/core/src/pin.rs:482:23
|
482 | impl<P: Deref<Target: Unpin>> Pin<P> {
| ^^^^^ required by this bound in `Pin::<P>::new`
So it seems that the trait Unpin is implemented for &val in line 6, but not in line 9. Why is that?
This has to do with some subtleties of type inference.
The variable on line 6 is inferred to be Pin<&i32> which later gets automatically upcast to Pin<&dyn TestTrait> on line 7. You can check this by inserting the following assignment after line 6, which forces a compile-time error that shows you the type of my_val:
let _: () = my_val;
= note: expected unit type `()`
found struct `Pin<&i32>`
(Side note: this won't work if my_val has type () -- then the assignment will succeed!)
In contrast, when you create the Pin as a temporary on line 9, it is inferred to be Pin<&dyn TestTrait> instead of Pin<&i32>, and &dyn TestTrait doesn't implement Unpin by default.
You can fix this by explicitly specifying the type argument T of Pin<T> to be &i32 on line 9:
f(Pin::<&i32>::new(&val));
You could also fix this by specifying a bound on TypeTrait of Unpin, which will cause &dyn TestTrait to implement Unpin as well:
trait TestTrait: Unpin {}
Finally, you could also fix the issue by changing f to accept Pin<&impl TestTrait> instead of Pin<&dyn TestTrait>:
fn f(_val: Pin<&impl TestTrait>) {}
As pointed out by #KevinReid, you can also indicate that the trait object must implement Unpin, which is allowed because Unpin has no methods:
fn f(_val: Pin<&(dyn TestTrait + Unpin)>) {}

Failure to apply turbofish notation on (boxed) trait objects

I can create a Write trait object that points to a (heap-stored) File object as such:
let a : Box<dyn Write> = Box::new(File::open("/dev/null").unwrap()); // Compiles fine.
Using the turbofish notation, however, produces an error (Rust 1.56.1):
let a : Box<dyn Write> = Box::<dyn Write>::new(File::open("/dev/null").unwrap()); // Fails to compile.
The error being:
error[E0599]: the function or associated item `new` exists for struct `Box<dyn std::io::Write>`, but its trait bounds were not satisfied
--> src/main.rs:37:48
|
37 | let a : Box<dyn Write> = Box::<dyn Write>::new(File::open("/dev/null").unwrap()); // Fails to compile.
| ^^^ function or associated item cannot be called on `Box<dyn std::io::Write>` due to unsatisfied trait bounds
|
::: /home/[REDACTED]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/mod.rs:1368:1
|
1368 | pub trait Write {
| --------------- doesn't satisfy `dyn std::io::Write: Sized`
|
= note: the following trait bounds were not satisfied:
`dyn std::io::Write: Sized`
I've been poking at the problem for the better part of a day. Either I'm missing something fundamental, or the special language treatment of Box is at play here (but I don't see how).
Your code is actually quite deceptive.
let a: Box<dyn Write> = Box::new(File::open("/dev/null").unwrap());
doesn't actually create a Box<dyn Write> like you think. It first creates a Box<File>, then the Box<File> is cast into a Box<dyn Write>. If you turbofish with File, then it works:
let a: Box<dyn Write> = Box::<File>::new(File::open("/dev/null").unwrap());
So, if you want to be explicit about the type, use an as cast instead of turbofish:
// a is Box<dyn Write>
let a = Box::new(File::open("/dev/null").unwrap()) as Box<dyn Write>;

Rust Vulkano how to reuse command buffer

I've precomputed one command buffer per frame and now I'd like to submit them in loop. I have this piece of code so far
let command_buffer = &command_buffers[image_num];
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(queue.clone(), swapchain.clone(), image_num)
.then_signal_fence_and_flush();
However this yields
let command_buffer = &command_buffers[image_num];
| ^^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&PrimaryAutoCommandBuffer` will meet its required lifetime bounds
--> src\main.rs:442:22
|
442 | .then_execute(queue.clone(), command_buffer)
I can see that the function expects static lifetime
fn then_execute<Cb>(
self,
queue: Arc<Queue>,
command_buffer: Cb,
) -> Result<CommandBufferExecFuture<Self, Cb>, CommandBufferExecError>
where
Self: Sized,
Cb: PrimaryCommandBuffer + 'static,
Perhaps I should clone this buffer similarly to the way it's done here
https://github.com/bwasty/vulkan-tutorial-rs/blob/f2f6935914bec4e79937b8cac415683c9fbadcb1/src/bin/15_hello_triangle.rs#L523
However, In version vulkano = "0.24.0" cloning is no longer implemented for PrimaryCommandBuffer

Rust "doesn't have a size known at compile-time" error for iterators?

I'm refactoring the cartesian product code in Rust's itertools [1] as a way of learning Rust. The cartesian product is formed from an Iterator I and an IntoIterator J. The IntoIterator J is converted into an iterator multiple times and iterated over.
So far I have the code below, which is a minor modification of the code in the itertools source code. The biggest change is specifying a specific type (i8) instead of using generic types.
struct Product {
a: dyn Iterator<Item=i8>,
a_cur: Option<i8>,
b: dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
b_iter: dyn Iterator<Item=i8>
}
impl Iterator for Product {
type Item = (i8, i8);
fn next(&mut self) -> Option<Self::Item> {
let elt_b = match self.b_iter.next() {
None => {
self.b_iter = self.b.into_iter();
match self.b_iter.next() {
None => return None,
Some(x) => {
self.a_cur = self.a.next();
x
}
}
}
Some(x) => x
};
match self.a_cur {
None => None,
Some(ref a) => {
Some((a, elt_b))
}
}
}
}
fn cp(i: impl Iterator<Item=i8>, j: impl IntoIterator<Item=i8>) -> Product {
let p = Product{
a: i,
a_cur: i.next(),
b: j,
b_iter: j.into_iter()};
return p
}
fn main() {
for foo in cp(vec![1,4,7], vec![2,3,9]) {
println!("{:?}", foo);
}
}
Unfortunately the compiler is giving errors I have been unable to fix. I've attempted the fixes suggested by the compiler, but when I make them I get many more "doesn't have size known at compile time" errors.
I'm especially confused because the implementation in Rust's itertools library (link below) has a very similar structure and didn't require specifying lifetimes, borrowing, using Boxes, or the dyn keyword. I'd love to know what I changed that led to the Rust compiler suggesting using borrowing and/or Boxes.
error[E0277]: the size for values of type `(dyn Iterator<Item = i8> + 'static)` cannot be known at compilation time
--> src/main.rs:15:8
|
15 | a: dyn Iterator<Item=i8>,
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = i8> + 'static)`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
15 | a: &dyn Iterator<Item=i8>,
| ^
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
15 | a: Box<dyn Iterator<Item=i8>>,
| ^^^^ ^
error[E0277]: the size for values of type `(dyn IntoIterator<Item = i8, IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)` cannot be known at compilation time
--> src/main.rs:17:8
|
17 | b: dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn IntoIterator<Item = i8, IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
17 | b: &dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
| ^
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
17 | b: Box<dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>>,
| ^^^^ ^
error: aborting due to 2 previous errors
[1] Docs at https://nozaq.github.io/shogi-rs/itertools/trait.Itertools.html#method.cartesian_product and code at https://github.com/rust-itertools/itertools/blob/master/src/adaptors/mod.rs#L286 .
You didn't just change the item type, you also removed the generic iterator. In the itertools crate, there is:
pub struct Product<I, J>
where I: Iterator
{
a: I,
…
Meaning that a is an iterator whose exact type will be specified by the user (but still at compile time).
You have removed the generic I parameter and instead you have written:
pub struct Product
{
a: dyn Iterator<Item=i8>,
…
If that worked, it would mean that a is an iterator whose item type is u8 but whose exact type will be specified at runtime. Therefore at compile-time the compiler can't know the exact type of a nor how much space it should allocate to store a inside Product.
If you want your cartesian product to work for any iterator whose items are u8, you need to keep the generic parameter I with an extra constraint:
pub struct Product<I, J>
where I: Iterator<Item=u8>
{
a: I,
…
And a similar change will be required for J in impl Iterator.

Resources