note: cannot satisfy `_: DecoderRunnable<u8>` - rust

On this simple sketch I made, I'm trying to do use a trait called Runnable to run an Arc<dyn LockableOption<T>>:
use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError};
pub type LockableArc<T> = Arc<Mutex<Option<T>>>;
pub struct MutexGuardOptionRef<'a, T: ?Sized> {
pub mutex_guard: MutexGuard<'a, Option<Box<T>>>,
}
pub trait LockableOption<T: ?Sized>: Send + Sync {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>>;
}
impl<T: ?Sized + Send> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
unimplemented!()
}
}
pub trait Decoder<T>: Send {
}
pub struct FfmpegDecoder<T> {
x: T,
}
impl<T: 'static + Send> Decoder<T> for FfmpegDecoder<T> {
}
trait DecoderRunnable<T> {
fn run(s: Arc<dyn LockableOption<dyn Decoder<T>>>);
}
impl<T: 'static + Send> DecoderRunnable<T> for FfmpegDecoder<T> {
fn run(s_lockable: Arc<dyn LockableOption<dyn Decoder<T>>>) {
unimplemented!()
}
}
fn main() {
let r: LockableArc<Box<dyn Decoder<u8>>> = Arc::new(Mutex::new(Some(Box::new(FfmpegDecoder{x: 0u8}))));
let rr: Arc<dyn LockableOption<dyn Decoder<u8>>> = Arc::new(r);
DecoderRunnable::<u8>::run(rr.clone());
}
Playground
I get the error:
error[E0283]: type annotations needed
--> src/main.rs:42:5
|
30 | fn run(s: Arc<dyn LockableOption<dyn Decoder<T>>>);
| --------------------------------------------------- required by `DecoderRunnable::run`
...
42 | DecoderRunnable::<u8>::run(rr.clone());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `_: DecoderRunnable<u8>`
which I don't get. Why anything here should satisfy DecoderRunnable? DecoderRunnable is a trait that has a run function that expects Arc<dyn LockableOption<dyn Decoder<T>>> and I'm passing rr which is exactly that.

Traits have to be implemented types so the compiler can figure out which implementation to run. In your example, DecoderRunnable is only implemented for FfmpegDecoder<T> and you're trying to call it on an Arc<dyn LockableOption<dyn Decoder<u8>>>, which has no implementation.
You can always specify which implementation needs to be called by using this syntax:
<FfmpegDecoder<u8> as DecoderRunnable::<u8>>::run(rr);
Although it doesn't seem like what you're trying to do . It's not clear what you're trying to abstract, since you also have the decoder deeply nested inside LockableArc<T>.
If you just want to add convenience methods to LockableArc<Box<dyn Decoder<u8>>>, you can add an impl block for Arc<dyn ...> , and make the run method take &self instead of Arc<dyn ...> as its first parameter.

Related

Why is a reference leaked from inside a lambda despite using clone?

I'm trying to implement the clone_into_box pattern in a piece of code the uses callbacks, and I'm running into an error I'm having trouble understanding.
Basically, I'm cloning the parameter of a lambda, but the borrow checker still complains I'm leaking a reference to said parameter.
My question: is this a case of the borrow checker being overly conservative (and if so, how can I re-write this in a way that would play nicely with the borrow checker), or is there something I'm missing here and a reference is indeed being leaked despite the clone?
Code:
pub trait CloneIntoBox{
fn clone_into_box<'a>(&self) -> Box<dyn CloneIntoBox + 'a>;
}
impl<'a> Clone for Box<dyn CloneIntoBox + 'a> {
fn clone(&self) -> Self {
self.as_ref().clone_into_box()
}
}
#[derive(Clone)]
pub struct StructWithBox<'a> {
pub my_box: Box<dyn CloneIntoBox + 'a>,
}
#[derive(Clone)]
struct StructThatCanBeClonedIntoBox {
pub data: u32,
}
impl CloneIntoBox for StructThatCanBeClonedIntoBox {
fn clone_into_box<'a>(&self) -> Box<dyn CloneIntoBox + 'a> {
Box::new(self.clone())
}
}
pub type WalkCallback<'a> = dyn FnMut(&StructWithBox) + 'a;
pub fn walk(data: Vec<u32>, cb: &mut WalkCallback) {
for d in data{
let instance = StructWithBox{my_box: Box::new(StructThatCanBeClonedIntoBox{data:d})};
cb(&instance);
}
}
fn main() {
let data = vec![1, 2];
let mut result = vec![];
walk(data, &mut|param| result.push((*param).clone()));
}
[Playground link]
Gives:
error[E0521]: borrowed data escapes outside of closure
--> src/main.rs:39:28
|
38 | let mut result = vec![];
| ---------- `result` declared here, outside of the closure body
39 | walk(data, &mut|param| result.push((*param).clone()));
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `param` escapes the closure body here
| |
| `param` is a reference that is only valid in the closure body
The problem is the 'a in StructWithBox. Consider the following implementation of walk():
impl<'b> CloneIntoBox for &'b u32 {
fn clone_into_box<'a>(&self) -> Box<dyn CloneIntoBox + 'a> {
Box::new(&42)
}
}
pub fn walk(data: Vec<u32>, cb: &mut WalkCallback) {
let data = 123u32;
let instance = StructWithBox {
my_box: Box::new(&data),
};
cb(&instance);
}
I haven't found a way to make this actually unsound: the only thing you can return from the impl CloneIntoBox for &u32 is a 'static reference, since 'a is decided by the caller. But the borrow checker doesn't know that: it assumes that 'a can be any lifetime in the callback, and then we push it into the vector outside the callback, but it can be freed after the callback is finished. So you can consider this overly conservative, or not.
To fix that you can make 'a always 'static in the callback:
pub type WalkCallback<'a> = dyn FnMut(&StructWithBox<'static>) + 'a;
Or get rid of the lifetime altogether:
pub trait CloneIntoBox {
fn clone_into_box(&self) -> Box<dyn CloneIntoBox>;
}
impl Clone for Box<dyn CloneIntoBox> {
fn clone(&self) -> Self {
self.as_ref().clone_into_box()
}
}
#[derive(Clone)]
pub struct StructWithBox {
pub my_box: Box<dyn CloneIntoBox>,
}
#[derive(Clone)]
struct StructThatCanBeClonedIntoBox {
pub data: u32,
}
impl CloneIntoBox for StructThatCanBeClonedIntoBox {
fn clone_into_box(&self) -> Box<dyn CloneIntoBox> {
Box::new(self.clone())
}
}
pub type WalkCallback<'a> = dyn FnMut(&StructWithBox) + 'a;
is equivalent to to
pub type WalkCallback<'a> = dyn for<'b> FnMut(&StructWithBox<'b>) + 'a;
which requires the callback to be able to take a StructWithBox of any lifetime 'c, as long as it is alive when the callback is called. Since the StructWithBox may not be valid any longer than that, it can't be pushed to a vector that lives longer than the callback.
Changing this to
pub type WalkCallback<'a, 'b> = dyn FnMut(&StructWithBox<'b>) + 'a;
allows the callback to only accept lifetimes longer than 'b.
In this case, 'b is inferred to be as long as result lives for, so that StructWithBox<'b> can be pushed to result.

Generic Trait for SQLx and reference

I have created a generic trait, and I am implementing it in a sqlx query, but I get an error
what am I doing wrong?
#[async_trait]
pub trait ITodoRepo<P> {
async fn list(pool:&P) -> Result<Vec<TodoType>>;
}
pub struct TodoRepo;
#[async_trait]
impl<P: sqlx::Executor<'static, Database = sqlx::Postgres>> ITodoRepo<P> for TodoRepo {
async fn list(pool: &P) -> Result<Vec<TodoType>> {
let rowset = sqlx::query_as!(
TodoSchema,
r#"SELECT * FROM todo"#)
.fetch_all(pool)
.await?
.iter()
.map(|row| hydrate(row))
.collect();
Ok(rowset)
}
}
How can I implement the Executor?
error[E0637]: `'_` cannot be used here
--> src/todo.rs:21:24
|
21 | .fetch_all(pool)
| ^^^^ the trait `sqlx::Executor<'_>` is not implemented for `&P`
In you question, as per fn list(pool: &P), the type of pool is &P. But the fetch_all() method seems to require an argument that implement trait sqlx::Executor<'_>. P implements that trait as per your impl but &P doesn't.
Here is a minimal reproducible code for your question:
trait MyTrait {}
struct MyStruct;
impl MyTrait for MyStruct {}
fn func<T: MyTrait>(arg: T) {
todo!()
}
fn main() {
let var = MyStruct;
let ref_to_var = &var;
func(ref_to_var);
}
Playground
Basically your function is expecting a type T that implements some trait MyTrait but you are passing &T.
To fix this, you can either change to function to accept a reference. Like in the above example:
fn func<T: MyTrait>(arg: &T) {
todo!()
}
Playground
Or you could implement the trait for the reference itself:
impl MyTrait for &MyStruct {}
Playground

Storing FnMut in struct gives lifetime problems

I'm trying to store a FnMut in a struct:
struct OpenVPNSocket {
socket_send_callback: Option<Box<dyn FnMut(Vec<u8>) -> Result<(), ()>>>,
}
impl OpenVPNSocket {
fn set_socket_send<F: FnMut(Vec<u8>) -> Result<(), ()>>(&mut self, callback: Box<F>) {
self.socket_send_callback = Some(callback);
}
}
I get this error:
error[E0310]: the parameter type `F` may not live long enough
--> src/lib.rs:8:42
|
7 | fn set_socket_send<F: FnMut(Vec<u8>) -> Result<(), ()>>(&mut self, callback: Box<F>) {
| -- help: consider adding an explicit lifetime bound...: `F: 'static +`
8 | self.socket_send_callback = Some(callback);
| ^^^^^^^^ ...so that the type `F` will meet its required lifetime bounds
I understand lifetime as something to do with references. However I don't use references. I don't see why my struct cannot store a Box. A Box lives as long as it's used.
UPDATE:
I have this example:
use std::sync::Arc;
pub type OnConsume = Arc<dyn Fn() -> Option<u8> + Send + Sync>;
struct Test {
callback: OnConsume
}
impl Test {
fn set_on_consume(&mut self, f: OnConsume) {
self.callback = f;
}
}
which works. What is the difference from the previous one?
In Rust, values also have lifetimes. Take, for example, this struct:
struct RefWrapper<'a> {
some_ref: &'a u32
}
An instance of RefWrapper is not a reference, but contains a lifetime. Since you're moving the box into the struct, which could live for the duration of the program (the method makes no guarantees as to when the struct instance could be dropped), the function must live for the maximum lifetime, the static lifetime.
All trait objects have lifetimes, the default implicit lifetime for boxed trait objects is 'static so your struct's socket_send_callback actually has an implicit + 'static bound. Shown in context:
struct OpenVPNSocket {
socket_send_callback: Option<Box<dyn FnMut(Vec<u8>) -> Result<(), ()> + 'static>>,
}
Since the boxed trait object has to be bounded by a 'static lifetime when you write a function to set this field the value itself must have a 'static lifetime which is why the compiler suggests adding that explicit bound. Fixed example with added bound:
impl OpenVPNSocket {
// notice the added 'static bound for F
fn set_socket_send<F: FnMut(Vec<u8>) -> Result<(), ()> + 'static>(&mut self, callback: Box<F>) {
self.socket_send_callback = Some(callback);
}
}
With this change your code will compile. If you want to accept trait objects that aren't bounded by 'static lifetimes then you can do that by making your OpenVPNSocket generic over lifetimes. This alternative solution also compiles:
struct OpenVPNSocket<'a> {
socket_send_callback: Option<Box<dyn FnMut(Vec<u8>) -> Result<(), ()> + 'a>>,
}
impl<'a> OpenVPNSocket<'a> {
fn set_socket_send<F: FnMut(Vec<u8>) -> Result<(), ()> + 'a>(&mut self, callback: Box<F>) {
self.socket_send_callback = Some(callback);
}
}
The reason why this code works is because you define the type once and use it in multiple places, and in all places it has the implicit 'static bound. Desugared:
use std::sync::Arc;
pub type OnConsume = Arc<dyn Fn() -> Option<u8> + Send + Sync + 'static>;
struct Test {
callback: OnConsume
}
impl Test {
fn set_on_consume(&mut self, f: OnConsume) {
self.callback = f;
}
}
However you can do the exact same thing in your prior code as well:
type Callback = Box<dyn FnMut(Vec<u8>) -> Result<(), ()>>;
struct OpenVPNSocket {
socket_send_callback: Option<Callback>,
}
impl OpenVPNSocket {
fn set_socket_send(&mut self, callback: Callback) {
self.socket_send_callback = Some(callback);
}
}
The above also compiles, and the implicit 'static bound is still there.

Implementing a trait for Option<T> and Option<&T>

Suppose there is a trait, whose methods all only take a reference of self, such as
trait Trait {
fn foo(&self) -> i32;
}
I'd like to have this trait implemented for both Option<T> and Option<&T> (as I can't always afford ownership), with a trivial implementation such as
impl<T: Trait> Trait for Option<T> {
fn foo(&self) -> i32 {
if let Some(inner) = self { return inner.foo(); }
0
}
}
impl<T: Trait> Trait for Option<&T> {
fn foo(&self) -> i32 {
if let Some(inner) = self { return inner.foo(); }
0
}
}
However, doing so produces the following error:
error[E0119]: conflicting implementations of trait `Trait` for type `std::option::Option<&_>`:
--> option.rs:12:1
|
5 | impl<T: Trait> Trait for Option<T> {
| ---------------------------------- first implementation here
...
12 | impl<T: Trait> Trait for Option<&T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::option::Option<&_>`
|
= note: downstream crates may implement trait `Trait` for type `&_`
Moreover, the implementations are literally the same. Is it possible to do this in a more compact way?
This does not compile because I, as a user of your trait could do something like this:
struct Yo;
impl Trait for Yo {
fn foo(&self) -> i32 { 0 }
}
impl Trait for &Yo {
fn foo(&self) -> i32 { 1 }
}
fn main() {
let a = Yo;
let b: Option<&Yo> = Some(&a);
b.foo(); // ambiguous call!
}
And there are two conflicting implementations of your trait for Option<&Yo>! Unfortunately trait specialization is still unstable, so that is probably not an option.
In your particular case you may solve with this generic impl, if you are willing:
impl<T: Trait> Trait for &T {
fn foo(&self) -> i32 {
(*self).foo()
}
}
This, combined with your generic impl for Option<T>, will give an unambiguous implementation for Option<&T>.

Private trait and E0119?

Is Rust has thing like "private trait"?
I mean trait defined without pub keyword is private?
Code bellow gives compilation error:
error[E0119]: conflicting implementations of trait `MyFrom<i64>` for type `std::option::Option<&_>`:
--> src/main.rs:22:1
|
16 | impl<T: Foo> MyFrom<i64> for Option<T> {
| -------------------------------------- first implementation here
...
22 | impl<T: Foo> MyFrom<i64> for Option<&T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::option::Option<&_>`
|
= note: downstream crates may implement trait `Foo` for type `&_`
But this is not public trait, and this is exe , how can " downstream crates may implement trait Foo for type &_" ? It is impossible to import trait from exe crate, and even if possible this is not pub trait,
so rustc doesn't support private traits?
fn main() {
trait MyFrom<T> {
fn my_from(_: T) -> Self;
}
trait Foo {}
impl<T: Foo> MyFrom<i64> for Option<T> {
fn my_from(x: i64) -> Self {
unimplemented!();
}
}
impl<T: Foo> MyFrom<i64> for Option<&T> {
fn my_from(x: i64) -> Self {
unimplemented!();
}
}
}

Resources