I can't seem to get the compiler to let me wrap a Tokio AsyncRead:
use std::io::Result;
use core::pin::Pin;
use core::task::{Context, Poll};
use tokio::io::AsyncRead;
struct Wrapper<T: AsyncRead>{
inner: T
}
impl<T: AsyncRead> AsyncRead for Wrapper<T> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8]
) -> Poll<Result<usize>> {
self.inner.poll_read(cx, buf)
}
}
This seems like it should compile but the compiler complains that I didn't include the proper trait bound even though poll_read is available through AsyncRead: Playground Link
error[E0599]: no method named `poll_read` found for type parameter `T` in the current scope
--> src/lib.rs:17:20
|
17 | self.inner.poll_read(cx, buf)
| ^^^^^^^^^ method not found in `T`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
What am I doing wrong?
Look at self in the signature for poll_read:
fn poll_read(
self: Pin<&mut Self>, // Self is pinned!
cx: &mut Context,
buf: &mut [u8]
) -> Poll<Result<usize>>
Self is pinned, meaning that poll_read can only be called on Pin<&mut T>'s! self.inner is of type T which is why the compiler cannot find poll_read on it. To fix this we have to somehow get pinned access to the field.
There's a whole section of the Rust Pin documentation on this and a whole crate dedicated to solving this issue.
Related
I want to implement a Stream that is based on a FuturesUnordered, which again is supposed to evaluate async functions with a return type of Result<SomeEnum>, though for simplicity of the argument let's assume it's only a Result<f64>. As async fns eventually return Futures, I assumed that the following way would be how I have to define my struct:
use anyhow::Result;
use futures::{Future, Stream, stream::FuturesUnordered};
use std::{pin::Pin, task::Poll};
use pin_project::pin_project;
#[pin_project]
pub struct MyDerivedStream<'a> {
#[pin]
from_futures: FuturesUnordered<&'a (dyn Future<Output = Result<f64>> + Send)>,
}
impl Stream for MyDerivedStream<'_> {
type Item = Result<f64>;
fn poll_next(
self: Pin<&mut Self>,
c: &mut std::task::Context<'_>,
) -> Poll<Option<<Self as Stream>::Item>> {
let this = self.project();
this.from_futures.poll_next(c)
}
}
The problem I'm running into now is that for some reason the poll_next function on the FuturesUnordered fails to compile due to not satisfying Stream trait bounds. (See for yourself on this Playground example):
error[E0599]: the method `poll_next` exists for struct `Pin<&mut FuturesUnordered<&dyn futures::Future<Output = std::result::Result<f64, anyhow::Error>> + std::marker::Send>>`, but its trait bounds were not satisfied
--> src/lib.rs:21:27
|
21 | this.from_futures.poll_next(c)
| ^^^^^^^^^ method cannot be called on `Pin<&mut FuturesUnordered<&dyn futures::Future<Output = std::result::Result<f64, anyhow::Error>> + std::marker::Send>>` due to unsatisfied trait bounds
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.14/src/stream/futures_unordered/mod.rs:55:1
|
55 | pub struct FuturesUnordered<Fut> {
| -------------------------------- doesn't satisfy `_: futures::Stream`
|
= note: the following trait bounds were not satisfied:
`&dyn futures::Future<Output = std::result::Result<f64, anyhow::Error>> + std::marker::Send: futures::Future`
which is required by `FuturesUnordered<&dyn futures::Future<Output = std::result::Result<f64, anyhow::Error>> + std::marker::Send>: futures::Stream`
I'm struggling to understand the problem here. For all I can see FuturesUnordered does implement Stream, so what is the actual issue here? Is is the &'a dyn Future - and if so, how else would I need to define the type here to make this work?
&'a dyn Future does not implement Future, which is required by impl Stream for FuturesUnordered. One solution would be replacing &'a dyn Future by Pin<&mut 'a dyn Future>:
use anyhow::Result;
use futures::{Future, Stream, stream::FuturesUnordered};
use std::{pin::Pin, task::Poll};
use pin_project::pin_project;
#[pin_project]
pub struct MyDerivedStream<'a> {
#[pin]
from_futures: FuturesUnordered<Pin<&'a mut(dyn Future<Output = Result<f64>> + Send)>>,
}
impl<'a> Stream for MyDerivedStream<'a> {
type Item = Result<f64>;
fn poll_next(
self: Pin<&mut Self>,
c: &mut std::task::Context<'_>,
) -> Poll<Option<<Self as Stream>::Item>> {
let this = self.project().from_futures;
this.poll_next(c)
}
}
It's necessary to mutably borrow the items in FuturesUnordered, this becomse evident by checking out the Futures::poll function which takes self: Pin<&mut Self>. The implementation of Stream for FuturesUnordered needs to poll the wrapped items in order to determine when a new item can be yielded, which is not possible with shared references.
Without the Pin around the &mut Future, it would be possible to mem::replace the wrapped future and cause that Future to never be actually polled.
This is a great resource to learn more about Pinning: https://fasterthanli.me/articles/pin-and-suffering
Following code does not compile because the element pulled from the vector does not implement the Pin<> type.
The error is in ele.poll() call
#[pin_project]
pub struct FifoCompletions<T, F>
where
F: Future<Output = Result<T, Error>>
{
#[pin]
pending: VecDeque<F>,
}
impl <T, F> FifoCompletions<T, F>
where
F: Future<Output = Result<T, Error>>
{
pub fn push(&mut self, f: F) {
self.pending.push_back(f);
}
}
impl <T, F> Future for FifoCompletions<T, F>
where
F: Future<Output = Result<T, Error>>
{
type Output = Result<T, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
while !this.pending.is_empty() {
match this.pending.front_mut() {
None => unreachable!(),
Some(ele) => {
let output = ready!(ele.poll(cx));
}
}
}
Poll::Pending
}
}
Error message is
no method named `poll` found for mutable reference `&mut F` in the current scope
method not found in `&mut F`
help: items from traits can only be used if the type parameter is bounded by the traitrustc(E0599)
sm.rs(66, 45): method not found in `&mut F`
Here's the literal answer to your question:
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
pub struct Completions<F>
where
F: Future<Output = ()>,
{
pending: Vec<F>,
}
impl<F> Future for Completions<F>
where
F: Future<Output = ()>,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// I copied this from Stack Overflow without reading the prose
// that describes why this is or is not safe.
// ... It's probably not safe.
let first = unsafe { self.map_unchecked_mut(|this| &mut this.pending[0]) };
first.poll(cx)
}
}
However, this is very likely to be unsafe and introduce undefined behavior. The problem is that the requirements for pinning are complex and nuanced. Specifically, once pinned, a value may never be moved in memory, including when it is dropped. From the docs, emphasis mine:
This can be tricky, as witnessed by VecDeque<T>: the destructor of VecDeque<T> can fail to call drop on all elements if one of the destructors panics. This violates the Drop guarantee, because it can lead to elements being deallocated without their destructor being called. (VecDeque<T> has no pinning projections, so this does not cause unsoundness.)
I checked with taiki-e, the author of the pin-project crate. A lightly-edited quote:
Operations such as Vec(Deque)'s push, insert, remove, etc. can move elements. If you want to pin elements, these methods should not be called without Unpin after they have been pinned. The pin API actually blocks this.
If the destructor moves elements, it is unsound to pin the element returned by accessors like get_mut, front_mut without Unpin.
Make the element Unpin or use a collection that can handle !Unpin futures like FutureUnordered instead of VecDeque.
Applied directly, the safest way to do this is:
use pin_project::pin_project; // 1.0
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
#[pin_project]
pub struct Completions<F>
where
F: Unpin,
F: Future<Output = ()>,
{
#[pin]
pending: Vec<F>,
}
impl<F> Future for Completions<F>
where
F: Unpin,
F: Future<Output = ()>,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let pending = this.pending.get_mut();
let first = Pin::new(&mut pending[0]);
first.poll(cx)
}
}
See also:
No method named `poll` found for a type that implements `Future`
When is it safe to move a member value out of a pinned future?
I have a struct that encapsulates File struct and I want this struct to implement AsyncRead trait so it could be used instead of File in some other part of the code:
struct TwoWayFile<'a> {
reader: &'a File,
}
impl<'a> AsyncRead for TwoWayFile<'a> {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
self.reader.poll_read(cx, buf)
}
}
According to the docs tokio::fs::File already implements tokio::io::AsyncRead but the compiler says the opposite:
error[E0599]: no method named `poll_read` found for reference `&'a tokio::fs::file::File` in the current scope
--> src/main.rs:44:21
|
44 | self.reader.poll_read(cx, buf)
| ^^^^^^^^^ method not found in `&'a tokio::fs::file::File`
What is missing here? Why I can't call the method that is already defined for File?
Your problem is likely that the poll_read method is implemented on Pin<&mut Self>, not on &self. This means you can only call it on a pinned mutable reference, and not a plain reference.
You can pin your reference on the heap using Box::pin or on the "async stack" using the pin_mut! macro, and should then be able to call the method.
I have a struct MyAsyncStream and tokio::io::AsyncWrite implementation for it:
impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for MyAsyncStream<S> {
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
....
}
I also have MyAsyncStreamWrapper:
struct MyAsyncStreamWrapper{inner: MyAsyncStream}
Now I want to implement AnotherTrait trait for MyAsyncStreamWrapper, with the following method:
impl AnotherTrait for MyAsyncStreamWrapper {
fn poll_send_to<B>(self: Pin<&Self>, cx: &mut Context<'_>, buf: &[u8], addr: B,) -> Poll<Result<usize, Self::Error>> {
Pin::new(&mut self.inner).poll_write(cx, buf)
}
....
}
In this method implementation, I want to call poll_write on the inner. But, unfortunately they are different on self mutability: Pin<&mut Self> vs Pin<&Self>. As expected it does not compile.
Is there an idiomatic "workaround" for such case? My idea is to wrap inner into Mutex so I could have mutable MyAsyncStream in the non-mutable context:
MyAsyncStreamWrapper{inner: Mutex<RefCell<MyAsyncStream>>}
...
fn poll_send_to<B>(mut self: Pin<&Self>, cx: &mut Context<'_>, buf: &[u8], addr: B,) -> Poll<Result<usize, Self::Error>> {
let rc = self.stream.lock().unwrap();
let ref mut inner = rc.borrow();
let pin = Pin::new(inner);
pin.poll_write(cx, buf);
}
...
But, unfortunately, it also does not compile, with the following error:
pin.poll_write(cx, buf);
^^^^^^^^^^ method not found in `std::pin::Pin<&mut std::cell::RefMut<'_, MyAsyncStream>>`
What is the right way to go?
Dereference then re-borrow seems to work:
use std::cell::RefCell;
use std::pin::Pin;
use std::sync::Mutex;
fn main() {
let a = Mutex::new(RefCell::new(42));
let rc = a.lock().unwrap();
let mut inner = rc.borrow_mut();
let pinned = Pin::new(&mut *inner);
print_type_name(pinned);
}
fn print_type_name<T>(_: T) {
println!("{}", std::any::type_name::<T>());
}
It outputs that the type is core::pin::Pin<&mut i32>.
That being said, using blocking synchronization primitives like Mutex in asynchronous context is probably not a good idea. If possible it is better to let poll_send_to take a Pin<&mut Self> parameter.
I'm having trouble understanding how references get forwarded through functions. The following scenario seems to compile as expected:
trait Trait {}
struct ImplementsTrait {}
impl Trait for ImplementsTrait {}
fn foo(t: &mut Trait) {
// ... use the mutable reference
}
fn forward(t: &mut Trait) {
foo(t); // forward the type '&mut Trait' to foo
}
fn main() {
let mut t = ImplementsTrait{};
forward(&mut t); // need to pass as reference because Trait has no static size
}
However, in using the API for the capnp crate, I get unexpected behavior:
fn parse_capnp(read: &mut BufRead) {
let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
Ok(())
}
fn main() {
// ... ///
let mut br = BufReader::new(f);
parse_capnp(&mut br);
Ok(())
}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:18:16
|
18 | let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
The signature of read_message is:
pub fn read_message<R>(
read: &mut R,
options: ReaderOptions
) -> Result<Reader<OwnedSegments>>
where
R: BufRead,
It appears that read is getting passed by value when it is a &mut BufRead and read_message is expecting a &mut BufRead. The only way to get this snippet to compile for me is changing this to:
fn parse_capnp(mut read: &mut BufRead) {
let reader = serialize_packed::read_message(&mut read, message::ReaderOptions::new());
Ok(())
}
I believe I am missing something simple about the types here. To me, this appears to pass a &mut &mut BufRead, which is not the expected type, but compiles.
Could someone add clarity to the types of read and t for the two examples?
I've looked at the following threads:
Use of mut in function signature
What are Rust's exact auto-dereferencing rules?
For the first thread, I'd say the comparison to C-style pointers is faulty due to the dereferencing rules that Rust applies.
Creating a Minimal, Complete, and Verifiable example that reproduces the problem is a useful step:
use std::io::BufRead;
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
{}
fn parse_capnp(read: &mut BufRead) {
read_message(read);
}
fn main() {}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:9:5
|
9 | read_message(read);
| ^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::io::BufRead`
note: required by `read_message`
--> src/main.rs:3:1
|
3 | / pub fn read_message<R>(read: &mut R)
4 | | where
5 | | R: BufRead,
6 | | {}
| |__^
The error message is well covered in existing questions:
Why does a generic method inside a trait require trait object to be sized?
What does "Sized is not implemented" mean?
Working with trait objects requiring sized
Why is the `Sized` bound necessary in this trait?
TL;DR: trait objects aren't guaranteed to have a size, but generics have a Sized trait bound by default.
read is getting passed by value
Yes, everything in Rust is always passed by value. Sometimes that value happens to be a reference though.
read_message is expecting a &mut BufRead
It is not. It is expecting a generic type that implements the trait BufRead. These two signatures are different:
// Reference to a concrete type
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
// Trait object
pub fn read_message<R>(read: &mut BufRead)
See also:
What is the difference between <T: Trait> Box<T> and &Trait / Box<Trait>?
What makes something a "trait object"?
a &mut &mut BufRead, which is not the expected type
It's a perfectly cromulent type. BufRead is implemented for any mutable reference to any type that implements BufRead itself:
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B
Besides, in this case you don't have a &mut &mut BufRead, you have a &mut &mut R. The concrete monomorphization for the types you've shown is actually a &mut &mut Bufreader.
You can fix it by :
changing the read_message function to accept unsized types. This is fine since R is always behind a pointer:
pub fn read_message<R>(read: &mut R)
where
R: ?Sized + BufRead,
changing the parse_capnp function to take a reference to a concrete type instead of a trait object:
fn parse_capnp<R>(read: &mut R)
where
R: BufRead,
{
read_message(read);
}
changing the parse_capnp function to take a concrete type instead of a trait object. You then need to take a reference to it yourself:
fn parse_capnp<R>(mut read: R)
where
R: BufRead,
{
read_message(&mut read);
}