I am in a &mut self function, I have a member field that is a Vec<u8>. I want to call a windows xxxA function (via the excellent winapi crate). I have no choice on the fn signature, it is implementing a trait.
I think I need to make a CString. So I tried
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
this doesn't work.
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\windbg.rs:51:36
|
51 | let str = CString::new(self.buf).unwrap();
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
I've read the explain of this but none of the 3 suggested solutions seem possible.
Here is the whole struct:
struct WinDbgWriter {
buf: Vec<u8>,
}
use std::io::Write;
impl std::io::Write for WinDbgWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
}
If we take your minimized case and try to borrow self.mut to avoid moving it (transferring its ownership), we get a new error which has a suggestion:
error[E0277]: the trait bound `Vec<u8>: From<&Vec<u8>>` is not satisfied
--> src/lib.rs:9:33
|
9 | let _str = CString::new(&self.buf).unwrap();
| ^^^^^^^^^
| |
| the trait `From<&Vec<u8>>` is not implemented for `Vec<u8>`
| help: consider adding dereference here: `&*self.buf`
|
= help: the following implementations were found:
<Vec<T> as From<&[T]>>
<Vec<T> as From<&mut [T]>>
<Vec<T> as From<BinaryHeap<T>>>
<Vec<T> as From<Box<[T]>>>
and 6 others
= note: required because of the requirements on the impl of `Into<Vec<u8>>` for `&Vec<u8>`
If we follow that suggestion, or explicitly coerce self.buf to a &[u8], then the code compiles.
CString::new takes an argument of some type Into<Vec<u8>>, but self.buf is, at this point of type &Vec<u8> because of it being accessed through a &self borrow, and there's no impl Into<Vec<u8>> for &Vec<u8>.
Related
piet is a drawing library with generic backends (cairo, for example).
I want to have a trait Renderable that can render to any piet backend (=context).
pub trait Renderable {
fn render<C: piet::RenderContext>(&self, ctx: &mut C);
// Since `Renderable` can render to any `RenderContext`, it can render to a file too.
fn save_to_file(&self, path: &Path) {
let ctx = build_cairo_context_for_image_file(path);
self.render::<piet_common::CairoRenderContext>(&mut ctx);
}
}
However rustc complained about object unsafety of render<C>, so I made the trait itself generic:
pub trait Renderable<C: piet::RenderContext> {
fn render(&self, ctx: &mut C);
fn save_to_file(&self, path: &Path) -> Result<(), piet_common::Error> {
let width = 512;
let height = 512;
let pix_scale = 1.0;
let mut device = piet_common::Device::new()?;
let mut bitmap: piet_common::BitmapTarget =
device.bitmap_target(width, height, pix_scale)?;
let mut rc = bitmap.render_context();
// Renderable::<CairoRenderContext>::render(self, &mut rc);
self.render(&mut rc);
rc.finish()?;
bitmap.save_to_file(path);
Ok(())
}
}
Now the problem is, when save_to_file calls self.render(&mut rc), it cannot find the method because save_to_file is implemented for C and not CairoRenderContext (although CairoRenderContext implements RenderContext).
|
14 | pub trait Renderable<C: piet_common::RenderContext> {
| - this type parameter
...
25 | self.render(&mut rc);
| ^^^^^^^ expected type parameter `C`, found struct `CairoRenderContext`
|
= note: expected mutable reference `&mut C`
found mutable reference `&mut CairoRenderContext<'_>`
As an awkward workaround, I added trait Drawable that is implemented for any type of Renderable<CairoRenderContext>. The problem is CairoRenderContext has a lifetime parameter, struct CairoRenderContext<'a>.
pub trait Renderable<C: piet_common::RenderContext> {
fn render(&self, ctx: &mut C);
}
pub trait Drawable {
fn save_to_file<'a>(&self, path: &Path) -> Result<(), piet_common::Error>
where
Self: Renderable<CairoRenderContext<'a>>,
{
let width = 512;
let height = 512;
let pix_scale = 1.0;
let mut device = piet_common::Device::new()?;
let mut bitmap: piet_common::BitmapTarget =
device.bitmap_target(width, height, pix_scale)?;
let mut rc = bitmap.render_context();
Renderable::<CairoRenderContext>::render(self, &mut rc);
// self.render(&mut rc);
rc.finish()?;
drop(rc);
bitmap.save_to_file(path);
// at this point, we don't need device, bitmap or rc.
// rustc thinks they should be alive.
Ok(())
}
}
The lifetime 'a is supposed to represent the lifetime of a local variable device but rustc errors that device and bitmap variables should live long enough for 'a.
1 error[E0597]: `device` does not live long enough
|
| fn save_to_file<'a>(&self, path: &Path) -> Result<(), piet_common::Error>
| -- lifetime `'a` defined here
...
| device.bitmap_target(width, height, pix_scale)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
| let mut rc = bitmap.render_context();
| ----------------------- assignment requires that `device` is borrowed for `'a`
...
| }
| - `device` dropped here while still borrowed
2 error[E0597]: `bitmap` does not live long enough
|
| fn save_to_file<'a>(&self, path: &Path) -> Result<(), piet_common::Error>
| -- lifetime `'a` defined here
...
| let mut rc = bitmap.render_context();
| ^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| assignment requires that `bitmap` is borrowed for `'a`
...
| }
| - `bitmap` dropped here while still borrowed
3 error[E0505]: cannot move out of `bitmap` because it is borrowed
|
| fn save_to_file<'a>(&self, path: &Path) -> Result<(), piet_common::Error>
| -- lifetime `'a` defined here
...
| let mut rc = bitmap.render_context();
| -----------------------
| |
| borrow of `bitmap` occurs here
| assignment requires that `bitmap` is borrowed for `'a`
...
| bitmap.save_to_file(path);
| ^^^^^^ move out of `bitmap` occurs here
Q1. When rustc errors about object-safety, was it a correct solution to uplift a type parameter from render<C> to Renderable<C>?
Q2. Should I have two traits (Renderable, Drawable) so save_to_file can call render or is there a better way?
Q3. How can I correctly tell rustc about Self: Renderable<CairoRenderContext<_>> in the last example?
Your second error, regarding the &mut C and &mut CairoRenderContext<'_> mismatch, is solved by omitting the body of save_to_file() from the trait definition, and instead defining it in the impl block. Here's a highly simplified version of what I mean:
pub trait Renderable<C: RenderContext> {
fn render(&self, ctx: &mut C);
fn save_to_file(&self);
}
struct Cairo;
impl Renderable<CairoRenderContext<'_>> for Cairo {
fn render(&self, ctx: &mut CairoRenderContext<'_>) {
todo!()
}
fn save_to_file(&self) {
let mut rc = CairoRenderContext::new();
self.render(&mut rc);
}
}
The original approach seems conceptually wrong in that the Renderable trait is supposed to be backend-agnostic, yet the default impl of save_to_file() was using types specific to Cairo, thus causing the error.
Q1
Moving the generic from the method to the trait is indeed one strategy to make a trait object-safe. Other strategies are
Making the method use dynamic dispatch for its arguments
Marking the method with where Self: Sized (though you won't be able to call that method using dynamic dispatch)
Q2
You don't need two traits if you used the approach I described.
Q3
The answer is a higher-ranked trait bound:
pub trait Drawable {
fn save_to_file(&self, path: &Path) -> ...
where
Self: for<'a> Renderable<CairoRenderContext<'a>>,
{...}
}
Note you can make the bound a supertrait instead:
pub trait Drawable: for<'a> Renderable<CairoRenderContext<'a>> {
fn save_to_file(&self, path: &Path) -> ... {...}
}
I need to implement a trait that is returning the futures::StreamExt trait.
In general this sounds easy and there are several answers to this e.g. this here.
I tried this with StreamExt but this does - for some reason - not work. Here my sample code:
// [dependencies]
// futures = "0.3.6"
// async-std = { version = "1.6.5", features = ["attributes", "unstable"] } // interval function is unstable atm.
use std::time::Duration;
use futures::StreamExt;
trait StreamProvidingTrait {
fn returnastream(self: &Self) -> Box<dyn StreamExt<Item=i32>>;
}
struct StreamProvider {}
impl StreamProvidingTrait for StreamProvider {
fn returnastream(self: &Self) -> Box<dyn StreamExt<Item=i32>> {
return Box::new(async_std::stream::interval(Duration::from_millis(1000)).map(|_| 1));
}
}
#[async_std::main]
async fn main() {
let mut counter = 0;
let object = StreamProvider {};
// creates a stream
let worx = object.returnastream();
// mappes the stream into something....
let mut mapped_stream = worx.map(|_| {
counter = counter + 1;
counter
});
// subscribing to the items
while let item = mapped_stream.next().await {
match item {
Some(value) => println!("{}", value),
_ => {}
}
}
}
And here the error:
Compiling traittest v0.1.0 (/Users/andre/repos/traittest)
warning: the trait `futures_util::stream::stream::StreamExt` cannot be made into an object
--> /Users/andre/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.6/src/stream/stream/mod.rs:1326:8
|
1326 | fn poll_next_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>
| ^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `poll_next_unpin` references the `Self` type in its `where` clause
|
= note: `#[warn(where_clauses_object_safety)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
error[E0038]: the trait `futures_util::stream::stream::StreamExt` cannot be made into an object
--> src/main.rs:6:36
|
6 | fn returnastream(self: &Self) -> Box<dyn StreamExt<Item=i32>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `futures_util::stream::stream::StreamExt` cannot be made into an object
|
::: /Users/andre/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.6/src/stream/stream/mod.rs:226:8
|
226 | fn next(&mut self) -> Next<'_, Self>
| ---- the trait cannot be made into an object because method `next` references the `Self` type in its return type
...
976 | fn by_ref(&mut self) -> &mut Self {
| ------ the trait cannot be made into an object because method `by_ref` references the `Self` type in its return type
...
1381 | fn select_next_some(&mut self) -> SelectNextSome<'_, Self>
| ---------------- the trait cannot be made into an object because method `select_next_some` references the `Self` type in its return type
error[E0038]: the trait `futures_util::stream::stream::StreamExt` cannot be made into an object
--> src/main.rs:12:36
|
12 | fn returnastream(self: &Self) -> Box<dyn StreamExt<Item=i32>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `futures_util::stream::stream::StreamExt` cannot be made into an object
|
::: /Users/andre/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.6/src/stream/stream/mod.rs:226:8
|
226 | fn next(&mut self) -> Next<'_, Self>
| ---- the trait cannot be made into an object because method `next` references the `Self` type in its return type
...
976 | fn by_ref(&mut self) -> &mut Self {
| ------ the trait cannot be made into an object because method `by_ref` references the `Self` type in its return type
...
1381 | fn select_next_some(&mut self) -> SelectNextSome<'_, Self>
| ---------------- the trait cannot be made into an object because method `select_next_some` references the `Self` type in its return type
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0038`.
error: could not compile `traittest`.
To learn more, run the command again with --verbose.
Process finished with exit code 101
When I exchange the StreamExt trait with my own one, this code works perfectly.
trait SomeTrait {
fn returnatrait(self: &Self) -> Box<dyn SomeOtherTrait>;
}
trait SomeOtherTrait {
fn sayHelloWorld(&self);
}
struct DummyStruct {}
impl SomeOtherTrait for DummyStruct {
fn sayHelloWorld(&self) {
println!("hello world");
}
}
struct Implementation {}
impl SomeTrait for Implementation {
fn returnatrait(self: &Self) -> Box<dyn SomeOtherTrait> {
return Box::new(DummyStruct{});
}
}
fn main() {
let implementation = Implementation{};
let worx = implementation.returnatrait();
worx.sayHelloWorld();
}
What's wrong here? There's obviously something I don't understand. Please help me understand this!
A function returning a trait can use the impl Trait syntax to return an opaque type that implements the trait. A trait method returning a trait currently doesn't support this feature and requires the trait to be returned as a trait object - a dynamically dispatched reference or smart pointer such as Box or Rc. Not all traits are object-safe, though, and the bad news is that StreamExt is among those that aren't, for reasons pointed out by the compiler, such as referencing Self in method return types and where clauses.
The good news, however, is that this is not a problem: StreamExt is an extension trait, one that provides a blanket implementation for all types that implement Stream. So you don't need to bother returning a dyn StreamExt trait object, you can return a dyn Stream one, and you'll still get access to StreamExt methods simply by requesting them with use StreamExt. In other words, you can just replace Box<dyn StreamExt> with Box<dyn Stream> in the return type of your trait.
Another issue you might encounter is that Box<dyn Stream> doesn't work on methods that need to move the stream, which includes many methods provided by StreamExt. Those will require the stream to be pinned, which can be fixed by returning Pin<Box<dyn Stream>> instead of Box<dyn Stream>. There is even a boxed() method on StreamExt that pins and boxes the stream in one operation; code that uses it would look like this (playground):
use futures::stream::{Stream, StreamExt};
use std::pin::Pin;
trait StreamProvidingTrait {
fn returnastream(&self) -> Pin<Box<dyn Stream<Item = i32>>>;
}
struct StreamProvider {}
impl StreamProvidingTrait for StreamProvider {
fn returnastream(&self) -> Pin<Box<dyn Stream<Item = i32>>> {
return tokio::stream::once(0).boxed();
}
}
fn main() {
let provider = StreamProvider {};
let stream = provider.returnastream();
let _fut = stream.into_future();
}
This code compiles:
struct BufRef<'a> {
buf: &'a [u8],
}
struct Foo<'a> {
buf_ref: BufRef<'a>,
}
impl<'a> Iterator for Foo<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
let result = &self.buf_ref.buf;
Some(result)
}
}
However, if I change BufRef to:
struct BufRef<'a> {
buf: &'a mut [u8],
}
The compiler says:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src\main.rs:12:5
|
12 | / fn next(&mut self) -> Option<Self::Item> {
13 | | let result = &self.buf_ref.buf;
14 | | Some(result)
15 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 9:6...
--> src\main.rs:9:6
|
9 | impl<'a> Iterator for Foo<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Why does changing the field to &'a mut [u8] cause the error?
Also, what does the compiler mean by this:
...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
I think that what is misleading you is that your code has a collapsed reference.
Your next function is basically equivalent to this code:
fn next(&mut self) -> Option<&'a [u8]> {
let result: &&'a [u8] = &self.buf_ref.buf;
Some(result)
}
This works because the double reference collapses to a single reference. In this case the double reference only obfuscates the code. Just write:
fn next(&mut self) -> Option<Self::Item> {
Some(self.buf_ref.buf)
}
And this works because references are always Copy.
But now what happens when you change your definition to &'a mut? You are probably guessing right now... mutable references are not Copy, so the same simple code will give you an easy-to-read error message:
cannot move out of self.buf_ref.buf which is behind a mutable reference
Naturally, you can reborrow a mutable ref as a const one, and then try to return it, but unfortunately this will not work because the the re-borrow cannot use the same lifetime as the mutable variable, it must be strictly smaller (or you could alias the pointed values). The compiler assigns the lifetime of this re-borrow as that of the next function, but now you cannot return this borrow, because it is a local reference!
Unfortunately, I don't know of any safe way to make your code compile. In fact I'm quite sure that it would create an unsound API. That is, if you managed to compile your code, then this safe code would create undefined behavior:
fn main() {
let mut buf = vec![1,2,3];
let buf_ref = BufRef { buf: &mut buf };
let mut foo = Foo { buf_ref };
let x: &[u8] = foo.next().unwrap();
//note that x's lifetime is that of buf, foo is not borrowed
//x and foo.buf_ref.buf alias the same memory!
//but the latter is mutable
println!("{}", x[0]); //prints 1
foo.buf_ref.buf[0] = 4;
println!("{}", x[0]); //prints what?
}
Let's try to compile this code:
use std::cell::RefCell;
struct Foo {
v: Vec<RefCell<u8>>,
}
impl Foo {
fn f(&self, i: usize) {
let t = &mut *self.v[i].borrow_mut();
//let t = &mut *{self.v[i].borrow_mut()}; //compiled ok
}
}
fn main() {}
Compilation error:
error[E0596]: cannot borrow field `self.v` of immutable binding as mutable
--> src/main.rs:9:23
|
8 | fn f(&self, i: usize) {
| ----- use `&mut self` here to make mutable
9 | let t = &mut *self.v[i].borrow_mut();
| ^^^^^^ cannot mutably borrow field of immutable binding
Why does this code require adding &mut self to function signature in order to compile?
This is a known issue where IndexMut is sometimes selected when Index should actually be used.
Your workaround of using {} is reasonable, but you can also use Index explicitly:
use std::cell::RefCell;
fn f(v: Vec<RefCell<u8>>) {
use std::ops::Index;
let _t = &mut v.index(0).borrow_mut();
}
fn main() {}
See also:
Why does a mutable borrow of a closure through DerefMut not work?
How to use `BorrowMut` contained within `RefCell`?
Another workaround is to explicitly call RefCell::borrow_mut(&v[0]).
Let's try to compile this code:
use std::cell::RefCell;
struct Foo {
v: Vec<RefCell<u8>>,
}
impl Foo {
fn f(&self, i: usize) {
let t = &mut *self.v[i].borrow_mut();
//let t = &mut *{self.v[i].borrow_mut()}; //compiled ok
}
}
fn main() {}
Compilation error:
error[E0596]: cannot borrow field `self.v` of immutable binding as mutable
--> src/main.rs:9:23
|
8 | fn f(&self, i: usize) {
| ----- use `&mut self` here to make mutable
9 | let t = &mut *self.v[i].borrow_mut();
| ^^^^^^ cannot mutably borrow field of immutable binding
Why does this code require adding &mut self to function signature in order to compile?
This is a known issue where IndexMut is sometimes selected when Index should actually be used.
Your workaround of using {} is reasonable, but you can also use Index explicitly:
use std::cell::RefCell;
fn f(v: Vec<RefCell<u8>>) {
use std::ops::Index;
let _t = &mut v.index(0).borrow_mut();
}
fn main() {}
See also:
Why does a mutable borrow of a closure through DerefMut not work?
How to use `BorrowMut` contained within `RefCell`?
Another workaround is to explicitly call RefCell::borrow_mut(&v[0]).