I know that nightly builds on Rust are "unstable" so there's no guarantee they continue to work with each update but I had a major issue with the rollout of rust 1.68.
The following code compiles for rust 1.67 but forms a cycle in 1.68.
The issue, specifically, is calling T::do_something.to_bytes which requires putting a where clause in the do_something function header. Adding [(); T::MyType::NLEN]:, to the where clause causes the breakage but also is required for generic constants. Any insight as to why this is happening which could help me learn more about Rust is much appreciated.
CODE:
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
fn main() {
println!("Hello, world!");
}
// FUNCTION THAT IS NOW BROKEN
fn do_something<T: SuperTrait>() where [(); T::MyType::LEN]:, [(); T::SUPER_SIZE]: {
let _ = T::do_something_super().to_bytes();
}
// Trait I implement for a few subtypes of my main type "SuperTrait"
trait MySerde {
const LEN: usize;
fn to_bytes(&self) -> [u8; Self::LEN];
fn from_bytes(bytes: [u8; Self::LEN]) -> Self;
}
// each subtrait would have its own requirements
trait SubTrait: MySerde {
// stuff
}
// We need a subtrait for constants or we get a cycle when defining SUPER_ARR
trait ConstantsForSuper {
const SUPER_SIZE: usize;
}
// in my actual example SuperTrait has several types implementing differeent subtraits
// (all of which require serde)
trait SuperTrait: ConstantsForSuper where [(); Self::SUPER_SIZE]: {
type MyType: SubTrait;
const SUPER_ARR: [Self::MyType; Self::SUPER_SIZE];
fn do_something_super() -> Self::MyType;
}
ERROR:
error[E0391]: cycle detected when building an abstract representation for `do_something::{constant#0}`
--> src/main.rs:8:45
|
8 | fn do_something<T: SuperTrait>() where [(); T::MyType::LEN]:, [(); T::SUPER_SIZE]: {
| ^^^^^^^^^^^^^^
|
note: ...which requires building THIR for `do_something::{constant#0}`...
--> src/main.rs:8:45
|
8 | fn do_something<T: SuperTrait>() where [(); T::MyType::LEN]:, [(); T::SUPER_SIZE]: {
| ^^^^^^^^^^^^^^
note: ...which requires type-checking `do_something::{constant#0}`...
--> src/main.rs:8:45
|
8 | fn do_something<T: SuperTrait>() where [(); T::MyType::LEN]:, [(); T::SUPER_SIZE]: {
| ^^^^^^^^^^^^^^
= note: ...which again requires building an abstract representation for `do_something::{constant#0}`, completing the cycle
note: cycle used when checking that `do_something` is well-formed
--> src/main.rs:8:1
|
8 | fn do_something<T: SuperTrait>() where [(); T::MyType::LEN]:, [(); T::SUPER_SIZE]: {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0391`.
error: could not compile `playground` due to previous error
Related
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.
I have the following code:
#[derive(Debug)]
struct S<'a> {
pub ss: Vec<String>,
pub rs: Vec<&'a str>, // each element in rs is a reference to the corresponding element in ss
}
impl<'a> S<'a> {
pub fn new() -> Self {
Self { ss: Vec::new(), rs: Vec::new() }
}
pub fn push(&mut self, s: String) {
self.ss.push(s);
self.rs.push(self.ss.last().unwrap());
}
}
fn main() {
let mut x = S::new();
let s = String::from("hello");
x.push(s);
// XXX: the following works!
// x.ss.push(s);
// x.rs.push(x.ss.last().unwrap());
// println!("hello world: {:#?}", x);
}
And the compiler generates the error:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:14:30
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:12:17
|
12 | pub fn push(&mut self, s: String) {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:14:22
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:7:6
|
7 | impl<'a> S<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:14:22
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground` due to previous error
However, the two lines below XXX does work!
How can I make the compiler happy?
Rust Playground
[EDIT]: of course, I have to admit that the design is flawed - what if an element is removed from ss, then without other compiler aware guarantees, the corresponding reference in rs would become dangling - the compiler can only be conservative here as to reject the code above. But, what about using unsafe Rust to achieve that, if the programmer can provide the safety guarantee?
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>.
Here's my test code:
use std::error::Error;
use std::fmt;
struct Handler {
error: String
}
#[derive(Debug)]
struct SpecificError;
impl fmt::Display for SpecificError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SpecificError")
}
}
impl Error for SpecificError {}
impl<E: Error> From<E> for Handler {
fn from(e: E) -> Self {
Handler { error: format!("{}", e) }
}
}
fn fail1() -> Result<(), SpecificError> {
Err(SpecificError)
}
fn fail2() -> Result<(), Box<Error>> {
Err(Box::new(SpecificError))
}
fn handler() -> Result<(), Handler> {
fail1()?;
fail2()?;
Ok(())
}
The call to fail1() is fine, but the call to fail2() doesn't compile:
error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
--> src/main.rs:35:5
|
35 | fail2()?;
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::error::Error`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<dyn std::error::Error>`
= note: required because of the requirements on the impl of `std::convert::From<std::boxed::Box<dyn std::error::Error>>` for `Handler`
= note: required by `std::convert::From::from`
I agree with the compiler that dyn Error doesn't have a size known at compile time, but I don't understand why that's relevant, since the type I'm attempting to convert from is a Box<dyn Error>, which does have a size known at compile time.
TL;DR: I'm pretty sure that you cannot in a generic way.
I don't understand why that's relevant, since the type I'm attempting to convert from is a Box<dyn Error>, which does have a size known at compile time.
That's not the place it's complaining about. Look at the error message again (slightly cleaned up):
the trait `Sized` is not implemented for `dyn Error`
required because of the requirements on the impl of `Error` for `Box<dyn Error>`
required because of the requirements on the impl of `From<Box<dyn Error>>` for `Handler`
required by `From::from`
The second line is the important one. Here's a simpler reproduction of your problem:
use std::error::Error;
fn example<E: Error>() {}
fn main() {
example::<Box<dyn Error>>();
}
error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
--> src/main.rs:6:5
|
6 | example::<Box<dyn Error>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::error::Error`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<dyn std::error::Error>`
note: required by `example`
--> src/main.rs:3:1
|
3 | fn example<E: Error>() {}
| ^^^^^^^^^^^^^^^^^^^^^^
Error is only implemented for Box<T> when T is Sized and implements Error itself:
impl<T: Error> Error for Box<T> {
// ...
}
Said another way, Box<dyn Error> does not implement Error.
One might think that you can add a second implementation of From for Box<Error>, but this is disallowed:
upstream crates may add new impl of trait `std::error::Error` for type
`std::boxed::Box<(dyn std::error::Error + 'static)>` in future versions
The best alternative I have to offer is to implement From for each individual concrete type you need to support:
impl From<SpecificError> for Handler {
fn from(e: SpecificError) -> Self {
Handler { error: format!("{}", e) }
}
}
impl From<Box<dyn Error>> for Handler {
fn from(e: Box<dyn Error>) -> Self {
Handler { error: format!("{}", e) }
}
}
A macro can reduce the boilerplate here.
While coding along to get used to Rust, I stumbled upon a compiler error. I want to understand why I get the error and what to do about it:
cannot infer an appropriate lifetime for lifetime parameter in generic
type due to conflicting requirements
I've been looking at a lot of questions covering similar errors, but most seem related to cyclic dependencies and I don't think this is what's going on here.
This is my attempt at a MWE, which still might be further reducible:
Playground link (slightly different error message)
pub struct InnerMut<T> {
state: u32,
stored_fn: fn(&mut T, u32),
}
impl<T> InnerMut<T> {
pub fn new(stored_fn: fn(&mut T, u32)) -> InnerMut<T> {
return InnerMut {
state: std::u32::MAX,
stored_fn,
};
}
pub fn mutate(&mut self, data: &mut T) {
(self.stored_fn)(data, self.state);
self.state -= 1;
}
}
pub struct StoreFnMut<F>
where
F: FnMut(&mut [u8]),
{
mutable_closure: F,
}
impl<F> StoreFnMut<F>
where
F: FnMut(&mut [u8]),
{
pub fn new(mutable_closure: F) -> StoreFnMut<F> {
StoreFnMut { mutable_closure }
}
fn run_closure_on_mutable_borrow(&mut self) {
let mut buf = vec![0; 100];
(self.mutable_closure)(&mut buf[..]);
}
}
fn foo(borrow: &mut &mut [u8], val: u32) {
borrow[0] = (val & 0xff) as u8;
}
fn main() {
let mut capturing_closure;
let mut store_fn_mut;
let mut inner_mut;
inner_mut = InnerMut::new(foo);
capturing_closure = move |mut borrow: &mut [u8]| {
inner_mut.mutate(&mut borrow);
};
store_fn_mut = StoreFnMut::new(capturing_closure);
store_fn_mut.run_closure_on_mutable_borrow();
}
I get this helpful looking yet confusing error message when compiling with Rust 1.24.1:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> src/main.rs:48:31
|
48 | inner_mut = InnerMut::new(foo);
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 49:25...
--> src/main.rs:49:25
|
49 | capturing_closure = move |mut borrow: &mut [u8]| {
| _________________________^
50 | | inner_mut.mutate(&mut borrow);
51 | | };
| |_____^
note: ...so that expression is assignable (expected &mut &mut [u8], found &mut &mut [u8])
--> src/main.rs:50:26
|
50 | inner_mut.mutate(&mut borrow);
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the block suffix following statement 2 at 46:5...
--> src/main.rs:46:5
|
46 | / let mut inner_mut;
47 | |
48 | | inner_mut = InnerMut::new(foo);
49 | | capturing_closure = move |mut borrow: &mut [u8]| {
... |
53 | | store_fn_mut.run_closure_on_mutable_borrow();
54 | | }
| |_^
note: ...so that variable is valid at time of its declaration
--> src/main.rs:46:9
|
46 | let mut inner_mut;
| ^^^^^^^^^^^^^
I can't possibly think of use case for &mut &mut _.
If you change foo to
fn foo(borrow: &mut [u8], val: u32);
Then you get another error:
error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
--> src/main.rs:46:25
|
46 | let mut inner_mut = InnerMut::new(foo);
| ^^^^^^^^^^^^^ `[u8]` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
note: required by `<InnerMut<T>>::new`
Well, nothing requires T to be Sized in this code as it's only used in references, so let's add the constraint T: ?Sized:
pub struct InnerMut<T: ?Sized> {
state: u32,
stored_fn: fn(&mut T, u32),
}
impl<T: ?Sized> InnerMut<T> {
// …
}
And this works.
What you are experiencing is that the compiler cannot prove that you are not storing a reference to &mut borrow inside mutate() into your InnerMut instance. This would be problematic as for all it knows the parameter to your closure lives shorter than the closure itself. But InnerMut was moved to the closure and must live longer than borrow.
Basically Rust prevents closure arguments from escaping the closure because it does not know how to infer lifetimes then.
Consider this minimal example:
struct Test<T> {
field: fn(T),
}
impl<T> Test<T> {
fn foo(&self, _val: T) {}
}
fn calc(_: &mut i32) {}
fn main() {
let test: Test<&mut i32> = Test { field: calc };
let _ = move |y: i32| {
test.foo(&mut y);
};
}
It is written in a way so that the compiler understands it better so we can understand the error:
error[E0597]: `y` does not live long enough
--> src/main.rs:15:23
|
15 | test.foo(&mut y);
| ^ borrowed value does not live long enough
16 | };
| - `y` dropped here while still borrowed
17 | }
| - borrowed value needs to live until here
But I do not even have fields of that type in my struct
One key principle of Rust is that your function signature is the barrier for error reporting. The function itself is checked against the signature and the callers are checked against the signature. That prevents reporting confusing errors about function bodies to the caller of functions (who did not even write them).
For all that Rust knows, your T is inferred as &mut u[8] and your mutate() captures a mutable self. That is suspicious. Better prevent that potential escape of closure variables.
But slightly changing the code makes it work
Rejecting all programs that are incorrect and accepting all programs that are correct is not decidable. Therefore Rust errs on the side of caution and rejects correct programs. Therefore some slight changes can make it possible for Rust to accept the program even if the program was correct before.
What does this mean for my code?
I really do not know the compiler well enough to answer this question. My guess is that by changing T to [u8] and the absence of explicit lifetimes from the InnerMut type the compiler can prove that your closure variables are not escaping.