struct Foo(i32);
impl<'a> Into<i32> for &'a Foo {
fn into(self) -> i32 {
self.0
}
}
fn test<I: Into<i32>>(i: I) {
let n: i32 = i.into();
println!("{}", n);
}
fn main() {
let f = Foo(42);
test(&f);
}
playground
This works but just looking at test
fn test<I: Into<i32>>(i: I) {
let n: i32 = i.into();
println!("{}", n);
}
The function can access both a borrow and a move/copy depending on how the Into trait is implemented.
impl<'a> Into<i32> for &'a Foo
// vs
impl Into<i32> for Foo
Now the user could try to call test like test(f); instead of test(&f); and would receive the following error message.
error[E0277]: the trait bound `i32: std::convert::From<Foo>` is not satisfied
--> <anon>:16:5
|
16 | test(f);
| ^^^^ trait `i32: std::convert::From<Foo>` not satisfied
|
Would it be possible to always force a borrow? Something similar to this
fn test<I: Into<i32>>(i: &I) {
let n: i32 = i.into();
println!("{}", n);
}
So that the user would get an error message similar to, "Expected &XX but found YY".
A where-clause works here by specifying the lifetime:
fn test<'a, I>(i: &'a I) where &'a I: Into<i32> {
let n: i32 = i.into();
println!("{}", n);
}
Now when you attempt to build with test(f);, the message is clearer:
error[E0308]: mismatched types
--> src/main.rs:16:10
|
16 | test(f);
| ^
| |
| expected `&Foo`, found struct `Foo`
| help: consider borrowing here: `&f`
Related
I am trying to make an iterator out of some struct, s1, that has references within it with some lifetimes, say 'a and 'b. The iterator elements are new instances of the same struct type holding the same references. When I try to do this, the iterator elements appear to become subject to the lifetime of s1 instead of just 'a and 'b.
An example for clarity:
#[derive(Debug)]
pub struct MyStruct<'a, 'b> {
num: i32,
ref1: &'a i32,
ref2: &'b i32,
}
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct> {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct{ num: 0, ref1: &i1, ref2: &i2 };
let s_next: Vec<_> = s1.with_next_nums(3).collect();
drop(s1); // commenting this line the program compiles
println!("{:?}", s_next);
}
The error I get is:
error[E0505]: cannot move out of `s1` because it is borrowed
--> src/main.rs:19:10
|
18 | let s_next: Vec<_> = s1.with_next_nums(3).collect();
| -------------------- borrow of `s1` occurs here
19 | drop(s1); // commenting this line the program compiles
| ^^ move out of `s1` occurs here
20 | println!("{:?}", s_next);
| ------ borrow later used here
For more information about this error, try `rustc --explain E0505`.
error: could not compile `playground` due to previous error
So, because I am dropping s1, Rust assumes the elements of s_next will become invalid, even though s_next only holds references to i1 and i2.
I suppose it is a matter of lifetime annotation, but I don't know how to fix it. If I were just producing a single struct out of s1, then I could annotate the return type like MyStruct<'a, 'b> and it would work, but just using impl Iterator<Item=MyStruct<'a, 'b>> as a return type does not solve it.
The problem with your version is that because of the lifetime elision rules, since you didn't specify the lifetimes for 'a and 'b in the returned MyStruct, the compiler assumes they have the same lifetime as self. So, this as if you wrote:
pub fn with_next_nums<'c>(&'c self, n: i32) -> impl Iterator<Item = MyStruct<'c, 'c>>
To fix that you need to explicitly declare the lifetimes as 'a and 'b:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>>
Now there will be another error in the declaration of with_next_nums(), because it does borrow from self as the closure captures it. You can fix that by adding '_, as the compiler suggests, but then your iterator will borrow from self, so your code (that collects them into a Vec) will work, but similar code that does not collect() immediately will not:
fn main() {
let i1 = 1;
let i2 = 2;
let s1 = MyStruct {
num: 0,
ref1: &i1,
ref2: &i2,
};
// The iterator is still alive when we drop `s1`, but it borrows from it.
let s_next = s1.with_next_nums(3);
drop(s1);
let s_next: Vec<_> = s_next.collect();
println!("{:?}", s_next);
}
A better fix is to change the closure so it will only borrow the fields it needs and not self. You can do it like that:
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item = MyStruct<'a, 'b>> {
let MyStruct { num, ref1, ref2 } = *self;
(1..=n).map(move |i| MyStruct {
num: num + i,
ref1,
ref2,
})
}
The problem is that in this case you need to specify the lifetime of both the iterator elements and the iterator itself. If you just specify the lifetimes of the iterator elements (with impl Iterator<Item=MyStruct<'a, 'b>>), the compiler assumes you will deal with lifetimes by hand and will give up trying to automatically assign a lifetime to the iterator. However, it does need to have the lifetime of the struct, because it depends on it, so it will fail to compile. The compiler error will actually give you the fix in this case:
error[E0700]: hidden type for `impl Iterator<Item = MyStruct<'a, 'b>>` captures lifetime that does not appear in bounds
--> src/main.rs:10:9
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> {
| ----- hidden type `Map<RangeInclusive<i32>, [closure#src/main.rs:10:21: 10:24]>` captures the anonymous lifetime defined here
10 | (1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl Iterator<Item = MyStruct<'a, 'b>>` captures `'_`, you can add an explicit `'_` lifetime bound
|
9 | pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
| ++++
For more information about this error, try `rustc --explain E0700`.
error: could not compile `playground` due to previous error
So, you just need to also add that + '_ to the return type to solve the issue:
impl<'a, 'b> MyStruct<'a, 'b> {
pub fn with_next_nums(&self, n: i32) -> impl Iterator<Item=MyStruct<'a, 'b>> + '_ {
(1..=n).map(|i| MyStruct { num: self.num + i, ref1: self.ref1, ref2: self.ref2 })
}
}
I'm trying to implement parts of the minecraft protocol (https://wiki.vg/).
I've successfully implemented a decoder to decode packets. But I'm stuck with the encoding part. The thing is that the minecraft protocol uses "minecraft varints" (https://wiki.vg/Protocol#VarInt_and_VarLong) and I want to have methods to write data as varints.
So my goal is to have a trait named Encoder with these methods:
fn write_var_int(&mut self, value: i32) -> Result<(), error::EncodeError>;
fn write_var_long(&mut self, value: i64) -> Result<(), error::EncodeError>;
fn write_string(&mut self, value: &str) -> Result<(), error::EncodeError>;
At the moment, I've only written the code for the first method:
fn write_var_int(&mut self, mut value: i32) -> Result<(), error::EncodeError> {
loop {
let mut byte = (value & 0b01111111) as u8;
if byte == 0 {
self.write_u8(byte).unwrap();
break;
}
self.write_u8(byte | 0b10000000).unwrap();
value = value >> 7;
}
Ok(())
}
In main.rs I import the module Encoder and I try to use it on a cursor :
let test = [0; 17];
let mut wrt = Cursor::new(test);
wrt.write_var_int(packet.id);
But I get these compilation errors:
error[E0599]: the method `write_var_int` exists for struct `std::io::Cursor<[{integer}; 17]>`, but its trait bounds were not satisfied
--> src/main.rs:57:37
|
57 | ... wrt.write_var_int(packet.id);
| ^^^^^^^^^^^^^ method cannot be called on `std::io::Cursor<[{integer}; 17]>` due to unsatisfied trait bounds
|
::: /home/clement/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/cursor.rs:75:1
|
75 | pub struct Cursor<T> {
| --------------------
| |
| doesn't satisfy `std::io::Cursor<[{integer}; 17]>: Encoder`
| doesn't satisfy `std::io::Cursor<[{integer}; 17]>: std::io::Write`
|
note: the following trait bounds were not satisfied because of the requirements of the implementation of `Encoder` for `_`:
`std::io::Cursor<[{integer}; 17]>: std::io::Write`
--> src/protocol/encoder.rs:12:16
|
12 | impl<W: Write> Encoder for W {
| ^^^^^^^ ^
warning: unused import: `protocol::encoder::Encoder`
--> src/main.rs:11:5
|
11 | use protocol::encoder::Encoder;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0599`.
warning: `eupim` (bin "eupim") generated 2 warnings
error: could not compile `eupim` due to previous error; 2 warnings emitted
I don't understand why the import of the Encoder module is marked as unused, and how to fix these errors.
I'll be pleased to have hints on how to fix this.
Thanks!
I tried to turn the code in your question into a minumal reproducible example:
use std::io::{Cursor, Write};
use std::slice;
mod error {
#[derive(Debug)]
pub enum EncodeError { }
}
trait Encoder {
fn write_u8(&mut self, value: u8) -> Result<(), error::EncodeError>;
fn write_var_int(&mut self, value: i32) -> Result<(), error::EncodeError>;
}
impl<W: Write> Encoder for W {
fn write_u8(&mut self, value: u8) -> Result<(), error::EncodeError> {
self.write(slice::from_ref(&value)).unwrap();
Ok(())
}
fn write_var_int(&mut self, mut value: i32) -> Result<(), error::EncodeError> {
loop {
let mut byte = (value & 0b01111111) as u8;
if byte == 0 {
self.write_u8(byte).unwrap();
break;
}
self.write_u8(byte | 0b10000000).unwrap();
value = value >> 7;
}
Ok(())
}
}
fn main() {
let test = [0; 17];
let mut wrt = Cursor::new(test);
wrt.write_var_int(3);
}
This produces the error:
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `write_var_int` exists for struct `std::io::Cursor<[{integer}; 17]>`, but its trait bounds were not satisfied
--> src/main.rs:39:9
|
39 | wrt.write_var_int(3);
| ^^^^^^^^^^^^^ method cannot be called on `std::io::Cursor<[{integer}; 17]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied because of the requirements of the implementation of `Encoder` for `_`:
`std::io::Cursor<[{integer}; 17]>: std::io::Write`
--> src/main.rs:14:16
|
14 | impl<W: Write> Encoder for W {
| ^^^^^^^ ^
For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error
The problem here is that we've got a Cursor<[{integer}; 17]>, but Write is only implemented for a Cursor<&mut [u8]>, where &mut [u8] is a mutable reference to a u8 slice.
This makes sense if you think about it: Cursor wraps an in-memory buffer, but there's no need for it to take ownership of it.
So let's make sure we're passing a mutable slice to our Cursor:
fn main() {
let mut test = [0u8; 17];
let mut wrt = Cursor::new(&mut test[..]);
wrt.write_var_int(3);
}
This compiles as expected.
On the following:
pub fn a<
T: Copy,
R: AsRef<[T]>
>(
a_fn: &dyn Fn(&[R], &mut [u64]),
)
{
let mut result = vec![0, 3];
b(&[1,2,3], result.as_mut_slice());
}
fn b<T: Copy, R: AsRef<[T]>>(_: &[R], _: &mut [u64]) {
unimplemented!();
}
fn c() {
a::<u64, &[u64]>(&b);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=43d054772b15fa575cc75e87b4eb34d9
I'm trying to be generic on the type R, but eventually use a slice of u64. However, it looks like that [integer] does not implement AsRef<[T]>.
Error:
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `{integer}: AsRef<[_]>` is not satisfied
--> src/lib.rs:9:5
|
9 | b(&[1,2,3], result.as_mut_slice());
| ^ the trait `AsRef<[_]>` is not implemented for `{integer}`
|
= help: the following implementations were found:
<&T as AsRef<U>>
<&mut T as AsRef<U>>
<Arc<T> as AsRef<T>>
<Box<T, A> as AsRef<T>>
and 38 others
note: required by a bound in `b`
--> src/lib.rs:13:18
|
13 | fn b<T: Copy, R: AsRef<[T]>>(_: &[R], _: &mut [u64]) {
| ^^^^^^^^^^ required by this bound in `b`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
Change b to take R or &R rather than &[R]. &[R] == &[AsRef<[T]>] has nested slices which I take it is not your intention.
fn main() {
let mut result = vec![0, 3];
b(&[1,2,3], result.as_mut_slice());
}
fn b<T: Copy, R: AsRef<[T]>>(_: R, _: &mut [u64]) {
unimplemented!();
}
Playground
This question already has an answer here:
How to write a trait bound for adding two references of a generic type?
(1 answer)
Closed 2 years ago.
I'd like to write an Add operation supported Vector struct, and write a some trait that uses the Vector struct, so I wrote this.
use std::ops::*;
#[derive(Clone)]
struct Vector<T>(Vec<T>);
impl<'a, T> Add<&'a Vector<T>> for Vector<T>
where
T: AddAssign<&'a T>,
{
type Output = Vector<T>;
fn add(mut self, rhs: &'a Vector<T>) -> Self::Output {
self.0
.iter_mut()
.zip(rhs.0.iter())
.for_each(|(left, right)| {
*left += right;
});
self
}
}
trait SomeOperation<'a ,T>
where
T: AddAssign<&'a T>+Clone + 'a,
{
fn add(u:Vector<T>,v:&'a Vector<T>)->Vector<T>{
let w = u+v;
let x = v.clone()+&w;
x
}
}
But compilation error occurs.
21 | trait SomeOperation<'a ,T>
| -- lifetime `'a` defined here
...
27 | let x = v.clone()+&w;
| ^^
| |
| borrowed value does not live long enough
| requires that `w` is borrowed for `'a`
28 | x
29 | }
| - `w` dropped here while still borrowed
How can I avoid these types of error.
You talk about implementing AddAssign but your code tries to implement Add. Also, I couldn't figure out what SomeOperation was for. I added the Debug trait to the derive line.
use std::ops::*;
#[derive(Clone, Debug)]
struct Vector<T>(Vec<T>);
impl<'a, T> AddAssign<&'a Vector<T>> for Vector<T>
where
T: AddAssign<&'a T>
{
fn add_assign(&mut self, rhs: &'a Vector<T>) {
self.0
.iter_mut()
.zip(rhs.0.iter())
.for_each(|(left, right)| {
*left += right;
});
}
}
impl<'a, 'b, T> Add<& 'b Vector<T>> for & 'a Vector<T>
where
Vector<T>: AddAssign<& 'b Vector<T>>,
T: Clone,
{
type Output = Vector<T>;
fn add(self, other: & 'b Vector<T>) -> Self::Output {
let mut res: Vector<T> = self.clone();
res += other;
res
}
}
fn main() {
let mut v1: Vector<u32> = Vector(vec![1, 2, 3]);
let v2 = Vector(vec![4, 5, 6]);
println!("Add: {:?}", &v1 + &v2);
v1 += &v2;
println!("AddAssign{:?}", v1);
}
I want to use an API that I can modify reg:
struct Ctx;
trait Foo {}
trait Ex {
fn do_<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a>;
}
impl<F> Ex for F
where
F: for<'a> Fn(&'a mut Ctx) -> Box<Foo + 'a>,
{
fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> {
(*self)(ecx)
}
}
fn reg<F>(name: &str, ext: F)
where
F: Ex + 'static,
{
}
//My code starts here
struct Boo;
impl Boo {
fn f1<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a> {
unimplemented!();
}
}
fn main() {
let boo = Boo;
reg("aaa", move |cx| boo.f1(cx));
}
But I got an error:
error[E0271]: type mismatch resolving `for<'a> <[closure#src/main.rs:33:16: 33:36 boo:_] as std::ops::FnOnce<(&'a mut Ctx,)>>::Output == std::boxed::Box<Foo + 'a>`
--> src/main.rs:33:5
|
33 | reg("aaa", move |cx| boo.f1(cx));
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
|
= note: concrete lifetime that was found is lifetime '_#9r
= note: required because of the requirements on the impl of `Ex` for `[closure#src/main.rs:33:16: 33:36 boo:_]`
= note: required by `reg`
error[E0281]: type mismatch: `[closure#src/main.rs:33:16: 33:36 boo:_]` implements the trait `std::ops::Fn<(&mut Ctx,)>`, but the trait `for<'a> std::ops::Fn<(&'a mut Ctx,)>` is required
--> src/main.rs:33:5
|
33 | reg("aaa", move |cx| boo.f1(cx));
| ^^^ -------------------- implements `std::ops::Fn<(&mut Ctx,)>`
| |
| requires `for<'a> std::ops::Fn<(&'a mut Ctx,)>`
| expected concrete lifetime, found bound lifetime parameter 'a
|
= note: required because of the requirements on the impl of `Ex` for `[closure#src/main.rs:33:16: 33:36 boo:_]`
= note: required by `reg`
How can I fix this?
In real code my struct Boo contains some data,
and want to call reg for it twice, so I not implement trait Ex, but
try to use closure.
Looks like issue #38714.
While it is being fixed, you can directly implement Ex for Boo.
impl Ex for Boo {
fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> {
self.f1(ecx)
}
}
fn main() {
let boo = Boo;
reg("aaa", boo);
}
In real code my struct Boo contains some data, and want to call reg for it twice, so I not implement trait Ex, but try to use closure.
You'll not be able to do that with the code you provided. move |cx| boo.f1(cx) moves boo into the closure, and you can't use boo after that.
If you want to share data, you'll need to use Rc in Boo.