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?
Related
I'm sure this is a duplicate, but I can't find a question which matches my question, exactly since I have a couple extra requirements because I have to adhere to some traits that I can't control.
Here is my code. I apologize for the sort of convoluted example, but this was the most I could minimize it as I am trying to implement a custom serialization format using the serde library.
// Doesn't really matter what this struct contains, it just needs an owning method
struct SideStruct;
impl SideStruct {
fn something_side<A: TraitA>(&self, aval: A) {
println!("something sideways :)");
aval.something_a(42)
}
}
trait TraitA {
fn something_a(&mut self, data: u32); // this would be the meat of my logic
}
// Note that this struct has an explicit lifetime
struct MainStruct<'a> {
refr: &'a mut u32
}
// Note that I implement for a mutable reference to MainStruct
impl<'a> TraitA for &'a mut MainStruct<'a> {
fn something_a(&mut self, data: u32) {
// Completely arbitrary, can safely ignore this function body
*self.refr += data;
println!("We're finally doing something: {}", self.refr);
}
}
// Implementing for MainStruct itself
impl<'a> MainStruct<'a> {
// Note, I can't change the signature for this function because it implements a trait
fn something_indirect(&mut self, ss: &SideStruct) {
// here is where the error occurs!
ss.something_side(self)
}
}
fn main() {
let mut base_val: u32 = 42;
let ss = SideStruct {};
let mut main_val = MainStruct { refr: &mut base_val };
main_val.something_indirect(&ss);
}
This is the error I got:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:28:27
|
28 | ss.something_side(self)
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:27:27
|
27 | fn something_indirect(&mut self, ss: &SideStruct) {
| ^^^^^^^^^
note: ...so that the expression is assignable
--> src/main.rs:28:27
|
28 | ss.something_side(self)
| ^^^^
= note: expected `&mut MainStruct<'a>`
found `&mut MainStruct<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:26:6
|
26 | impl<'a> MainStruct<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:28:12
|
28 | ss.something_side(self)
| ^^^^^^^^^^^^^^
= note: expected `<&mut MainStruct<'a> as TraitA>`
found `<&mut MainStruct<'_> as TraitA>`
For more information about this error, try `rustc --explain E0495`.
I don't know what the compiler means when it states that note: first, the lifetime cannot outlive the anonymous lifetime defined here.... Does it mean that some constraint forces self to not outlast the method something_indirect? That makes no sense. Also the message so that the expression is assignable confuses me. MainStruct should not be assigned when something_side is called on it right? Since I implemented TraitA for a mutable reference to MainStruct, shouldn't I be able to call something_side with a mutable reference to MainStruct by passing self? Anyways, thanks for the help, and have a great day!
The trouble is that in order to use the method defined, you must borrow the MainStruct as mutable with an anonymous lifetime. In the code you wrote, you not only borrow the things within MainStruct for 'a, but also MainStruct itself. This is unnecessary since the borrow has an inferred lifetime. You can fix this by removing the 'a in the trait impl
impl<'a> TraitA for &mut MainStruct<'a> {
/*...*/
}
This should do the exact same thing, but removes the bug. The bug is trying to tell you that the code you wrote is buggy, because it borrows MainStruct using a lifetime in the struct itself.
So I have this trait and a struct that implements it:
trait Trait {
fn foo(&self) -> u64;
}
/// No Copy trait supported because it's expensive
struct Expensive {
id: u64,
}
impl Trait for Expensive {
fn foo(&self) -> u64 {
self.id
}
}
I have another structure that I wish to be global, that contains the trait:
struct Cheap {
pub item: Box<dyn Trait>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Box::new(Expensive {
id: 4
})
}
}
fn trait_item() -> Box<dyn Trait> {
CHEAP.with(|c| c.item)
}
This fails because
error[E0507]: cannot move out of `c.item` which is behind a shared reference
--> src/main.rs:35:20
|
35 | CHEAP.with(|c| c.item)
| ^^^^^^ move occurs because `c.item` has type `std::boxed::Box<dyn Trait>`, which does not implement the `Copy` trait
It's not really feasible to always do the processing within the .with(...) part, because some functions that take in the Trait don't care where it comes from. So I try to return a reference to it instead:
fn trait_item<'a>() -> &'a Box<dyn Trait> {
CHEAP.with(|c| &c.item)
}
This also fails because I cannot send a reference outside of the with:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 33:16...
--> src/main.rs:33:16
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 32:15...
--> src/main.rs:32:15
|
32 | fn trait_item<'a>() -> &'a Box<dyn Trait> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:5
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^^^^^^^^^^^^^
So instead I wrap the whole thing in an Rc like so:
struct Cheap {
pub item: Rc<Box<dyn Trait>>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Rc::new(Box::new(Expensive {
id: 4
}))
}
}
fn trait_item() -> Rc<Box<dyn Trait>> {
CHEAP.with(|c| c.item.clone())
}
But now clippy complains:
warning: usage of `Rc<Box<T>>`
--> src/main.rs:41:15
|
41 | pub item: Rc<Box<dyn Trait>>,
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= note: `#[warn(clippy::redundant_allocation)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: usage of `Rc<Box<T>>`
--> src/main.rs:53:20
|
53 | fn trait_item() -> Rc<Box<dyn Trait>> {
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: 2 warnings emitted
Am I missing something, or is it not actually possible to do what clippy recommends here?
Rust playground | Relevant Clippy page
You can wrap a trait object in a Rc as well, since Rc is also a pointer.
Therefore if you have Rc<Box<T>>, you have two allocations: One for the T and one for the Box (another pointer, that now is on the heap). Instead, use Rc<dyn MyTrait> to only have one allocation.
I had gotten an error in my code about lifetime inferrence, and I have been able to reduce the code to the following:
use std::collections::HashMap;
struct A<'a> {
x: &'a mut HashMap<&'a str, i32>,
}
impl<'a> A<'a> {
fn new(x: &'a mut HashMap<&'a str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
The error that results from this is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:13:17
|
13 | let a = A::new(self.x);
| ^^^^^^
|
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 test(&mut self) {
13 | | let a = A::new(self.x);
14 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 7:6...
--> src/main.rs:7:6
|
7 | impl<'a> A<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
= note: expected `&mut std::collections::HashMap<&str, i32>`
found `&mut std::collections::HashMap<&'a str, i32>`
I do not understand what is the error in this case, but I did find that if I add a lifetime 'b to struct A, such that the str reference in the HashMap has a lifetime of 'b, the codes does compile. Here is how the code looks like after the aforementioned change:
use std::collections::HashMap;
struct A<'a, 'b> {
x: &'a mut HashMap<&'b str, i32>,
}
impl<'a, 'b> A<'a, 'b> {
fn new(x: &'a mut HashMap<&'b str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
However, I have no idea why that change works. To my understanding, having both lifetimes be 'a means that A must live as long as the HashMap, and the HashMap must live as long as the &strs that are used as its keys, which I see no issue with. I also do not see how the change adds any additional information for the compiler. Can anyone please shed some light for me on this situation?
Change the A::test() function into
fn test(&'a mut self) { // Add lifetime specification
let a = A::new(self.x);
}
and it should work.
The compiler said it cannot infer lifetime for A::new(), and the first note mentioned "anonymous lifetime", that means the compiler doesn't know the lifetime of self.x in A::new(self.x). So we just need to tell the compiler that self has a lifetime of 'a.
I want to make a closure hold &mut Vec, but these simple few lines of code can't compile.
I know this can be solved with RefCell, I just can't figure the error out.
struct Server<'a> {
data: &'a mut Vec<i32>,
}
fn main() {
let mut data = vec![1, 2, 3];
let mut c = || {
Server{
data: &mut data,
}
};
let server = c();
}
Rust playground link
The error message is:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:36:19
|
36 | data: &mut data,
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 34:17...
--> src/main.rs:34:17
|
34 | let mut c = || {
| ^^
note: ...so that closure can access `data`
--> src/main.rs:36:19
|
36 | data: &mut data,
| ^^^^^^^^^
note: but, the lifetime must be valid for the call at 39:18...
--> src/main.rs:39:18
|
39 | let server = c();
| ^^^
note: ...so type `Server<'_>` of expression is valid during the expression
--> src/main.rs:39:18
|
39 | let server = c();
| ^^^
error: aborting due to previous error
Update:
I found this post answered the question, but I could not understand some parts of it:
It turns out that, returning &'a mut i32 is not feasible for the shorter-live invocation of call_mut. What we’ve really wanted for the return type of call_mut, was something like:
impl<'a> FnMut<(usize,)> for Closure<'a> {
extern "rust-call"
fn<'b> call_mut(&'b mut self, (i,): (usize, )) -> &'b mut i32 {
self.inner.get_mut(i).unwrap()
}
}
Why the call_mut fn has to use a 'b lifetime instead of 'a?
I found the code would work if change data: &mut Vec<i32> to data: &Vec<i32>, which makes me more confused that why lifetime is related to mut?
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.