conflicting lifetime requirements on implementing Clone for simple struct - rust

I'm designing a simple type to hold either a Vec<u8> or a slice (mut or not mut). I'm having problems on lifetime constraints and this time I don't know why there are conflicting requirements:
use std::vec::Vec;
pub enum EncodedPacket<'a> {
Owned(Vec<u8>),
Ref(&'a [u8]),
RefMut(&'a mut [u8])
}
impl<'a> EncodedPacket<'a> {
pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
EncodedPacket::Ref(slice)
}
pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
EncodedPacket::RefMut(slice)
}
pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
EncodedPacket::Owned(vec)
}
}
impl<'a> Clone for EncodedPacket<'a> {
fn clone(&self) -> Self {
match self {
EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
}
}
}
Playground
Error:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
--> src/lib.rs:28:35
|
28 | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 24:14...
--> src/lib.rs:24:14
|
24 | fn clone(&self) -> Self {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:28:35
|
28 | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
| ^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 23:6...
--> src/lib.rs:23:6
|
23 | impl<'a> Clone for EncodedPacket<'a> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:25:9
|
25 | / match self {
26 | | EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
27 | | EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
28 | | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
29 | | }
| |_________^
= note: expected `EncodedPacket<'a>`
found `EncodedPacket<'_>`
I'm just recreating EncodedPacket with the same internal things, I don't see why there are conflicting lifetime requirements at all.

You cannot clone a mutable reference. One way of doing this would be to wrap it in Rc and Rc<RefCell>:
use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
pub enum EncodedPacket<'a> {
Owned(Vec<u8>),
Ref(Rc<&'a [u8]>),
RefMut(Rc<RefCell<&'a mut [u8]>>)
}
impl<'a> EncodedPacket<'a> {
pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
EncodedPacket::Ref(Rc::new(slice))
}
pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
EncodedPacket::RefMut(Rc::new(RefCell::new(slice)))
}
pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
EncodedPacket::Owned(vec)
}
}
Playground

Related

Implement a trait for both Iter<&> and Iter<&mut> [duplicate]

This question already has answers here:
Conflicting trait implementations even though associated types differ
(2 answers)
Closed 9 months ago.
I am trying to write a conversion trait that can take both Iterators to references and Iterators to mutable references.
Sadly, it seems that once you implement a trait for Iter<&>, you cannot implement the trait also for Iter<&mut> as they seem to collide. Which doesn't make sense, though, because Iter<&mut> doesn't seem to be able to utilize the implementation for Iter<&>.
Here is a minimal example:
// A dummy object
#[derive(Debug)]
struct MyObj(i32);
// A collection of MyObj references
#[derive(Debug)]
struct RefVec<'a>(Vec<&'a MyObj>);
// Goal: create a conversion function that can take *either* a `Iterator<&MyObj>` *or* `Iterator<&mut MyObj>`.
// Attempt: Create a Conversion Trait and implement it for both of those types
trait ConvertToRefVec<'a> {
fn convert(&mut self) -> RefVec<'a>;
}
// Implement the conversion for Iter<&MyObj>
impl<'a, T> ConvertToRefVec<'a> for T
where
T: Iterator<Item = &'a MyObj>,
{
fn convert(&mut self) -> RefVec<'a> {
RefVec(self.collect::<Vec<_>>())
}
}
// Problem: the impl above does not apply to Iter<&mut MyObj>. But the attempt to write an impl
// for Iter<&mut MyObj> fails with the message that it collides with the impl above:
impl<'a, T> ConvertToRefVec<'a> for T
where
T: Iterator<Item = &'a mut MyObj>,
{
fn convert(&mut self) -> RefVec<'a> {
RefVec(self.collect::<Vec<_>>())
}
}
fn main() {
let owned = [MyObj(42), MyObj(69)];
let ref_vec = owned.iter().convert();
println!("{:?}", ref_vec);
let ref_vec = owned.iter_mut().convert();
println!("{:?}", ref_vec);
}
Which gives me:
error[E0119]: conflicting implementations of trait `ConvertToRefVec<'_>`
--> src/main.rs:27:1
|
16 | / impl<'a, T> ConvertToRefVec<'a> for T
17 | | where
18 | | T: Iterator<Item = &'a MyObj>,
19 | | {
... |
22 | | }
23 | | }
| |_- first implementation here
...
27 | / impl<'a, T> ConvertToRefVec<'a> for T
28 | | where
29 | | T: Iterator<Item = &'a mut MyObj>,
30 | | {
... |
33 | | }
34 | | }
| |_^ conflicting implementation
But if I leave out the impl for Iterator<&mut>, then I get this error:
error[E0599]: the method `convert` exists for struct `std::slice::IterMut<'_, MyObj>`, but its trait bounds were not satisfied
--> src/main.rs:42:36
|
42 | let ref_vec = owned.iter_mut().convert();
| ^^^^^^^ method cannot be called on `std::slice::IterMut<'_, MyObj>` due to unsatisfied trait bounds
|
::: /home/.../.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter.rs:187:1
|
187 | pub struct IterMut<'a, T: 'a> {
| -----------------------------
| |
| doesn't satisfy `<_ as Iterator>::Item = &MyObj`
| doesn't satisfy `std::slice::IterMut<'_, MyObj>: ConvertToRefVec`
|
note: trait bound `<std::slice::IterMut<'_, MyObj> as Iterator>::Item = &MyObj` was not satisfied
--> src/main.rs:18:17
|
16 | impl<'a, T> ConvertToRefVec<'a> for T
| ------------------- -
17 | where
18 | T: Iterator<Item = &'a MyObj>,
| ^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
So my question is: How can I write such a conversion mechanism that works with both Iterator<Item = &MyObj> and Iterator<Item = &mut MyObj?
The thing is that you are trying to implement your trait in two different ways for the same type. So the problem that you treat T as the same one. Then you can just split the cases for concrete types. Like to following:
#[derive(Debug)]
struct MyObj(i32);
#[derive(Debug)]
struct RefVec<'a>(Vec<&'a MyObj>);
trait ConvertToRefVec<'a> {
fn convert(&mut self) -> RefVec<'a>;
}
impl<'a> ConvertToRefVec<'a> for std::slice::Iter<'a, MyObj>
{
fn convert(&mut self) -> RefVec<'a> {
RefVec(self.collect::<Vec<_>>())
}
}
impl<'a> ConvertToRefVec<'a> for std::slice::IterMut<'a, MyObj>
{
fn convert(&mut self) -> RefVec<'a> {
RefVec(self.map(|el| &*el).collect::<Vec<&MyObj>>())
}
}
fn main() {
let mut owned = [MyObj(42), MyObj(69)];
let ref_vec = owned.iter().convert();
println!("{:?}", ref_vec);
let ref_vec = owned.iter_mut().convert();
println!("{:?}", ref_vec);
}

Lifetime error when creating mutable iterator

I had some problems when I tried to create a custom iterator. The non-mutable version worked fine but when copying the same function to create a mutable version, a lifetime error appeared. This is a simplified version of my problem:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item = &String> {
(start..=end).filter_map(move |i| {
self.map.get(&i)
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
(start..=end).filter_map(move |i| {
self.map.get_mut(&i)
})
}
}
The iter function works fine but the iter_mut function doesn't compile with this error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:21:22
|
21 | self.map.get_mut(&i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 20:34...
--> src/main.rs:20:34
|
20 | (start..=end).filter_map(|i| {
| ^^^
note: ...so that closure can access `self`
--> src/main.rs:21:13
|
21 | self.map.get_mut(&i)
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime defined on the method body at 19:21...
--> src/main.rs:19:21
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:19:57
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::option::Option<&mut std::string::String>`
found `std::option::Option<&mut std::string::String>`
As said Todd, compile error on iter_mut likely occurs due to creation many mutable references to the same HashMap, but I'm not sure about that. You can do something like that:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item=&String> {
self.map
.iter()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item=&mut String> {
self.map
.iter_mut()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
}

Problem with lifetimes and implementing Clone

I'm trying to define a struct representing a function that can be composed using different arithmetic operations (only addition has been implemented).
I would like to implement Clone for my struct, however I can't seem to it to work:
use std::ops::Add;
use std::boxed::Box;
use std::clone::Clone;
type InputT = i32;
type OutputT = f64;
pub struct ComposableFn<'a> {
f: Box<dyn 'a + Fn(InputT) -> OutputT>,
}
impl<'a> ComposableFn<'a> {
pub fn new<F: 'a + Fn(InputT) -> OutputT>(f: F) -> Self {
Self {
f: Box::new(f)
}
}
pub fn compute(&self, x: InputT) -> OutputT {
(self.f)(x)
}
}
impl<'a> Add<&'a ComposableFn<'a>> for &'a ComposableFn<'a> {
type Output = ComposableFn<'a>;
fn add(self, rhs: &'a ComposableFn) -> Self::Output {
ComposableFn::new(move |x| self.compute(x) + rhs.compute(x))
}
}
impl<'a> Clone for ComposableFn<'a> {
fn clone(&'a self) -> Self {
ComposableFn::new(move |x| self.compute(x))
}
}
fn main() {
let id = ComposableFn::new(|x| x.into());
println!("{}", id.compute(12));
let double = &id + &id;
println!("{}", double.compute(7));
let triple = &double + &id;
println!("{}", triple.compute(3));
}
When compiling I get the following error:
error[E0308]: method not compatible with trait
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&ComposableFn<'a>) -> ComposableFn<'_>`
found fn pointer `fn(&'a ComposableFn<'a>) -> ComposableFn<'_>`
note: the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 32:6
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
error: aborting due to previous error
Removing the 'a from fn clone(&'a self) results in the following error instead:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `&ComposableFn<'_>`
found `&ComposableFn<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 32:6...
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:34:9
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `ComposableFn<'a>`
found `ComposableFn<'_>`
error: aborting due to previous error
Is there a way to fix this?
You cannot implement Clone this way. Clone requires the return type to match exactly, which means the exact same lifetime 'a. But you're trying to make a clone that references self which has a different lifetime.
The straightforward solution would be to just clone f. Unfortunately, you can't clone a Box<dyn...>, at least not without some help. See: How to clone a struct storing a boxed trait object?
The only direct solution would be to swap Box out with Rc so they share ownership:
use std::rc::Rc;
pub struct ComposableFn<'a> {
f: Rc<dyn 'a + Fn(InputT) -> OutputT>,
}
impl Clone for ComposableFn<'_> {
fn clone(&self) -> Self {
ComposableFn { f: self.f.clone() }
}
}

Proxy method for implementing Iterator, conflicting lifetime

I'm trying to implement an iterator which simply proxies the next method to another method on the struct itself.
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}
I'm getting the conflicting requirements for lifetime error though:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:16:14
|
16 | self.name()
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/lib.rs:15:5
|
15 | / fn next(&mut self) -> Option<Self::Item> {
16 | | self.name()
17 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:16:9
|
16 | self.name()
| ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 13:6...
--> src/lib.rs:13:6
|
13 | impl<'a> Iterator for IterStruct<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Playground
How can I resolve this?
One solution is to specify that name outlives the IterStruct it is contained in:
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name<'s>(&'s mut self) -> Option<Element<'a>>
where
'a: 's, // <- specify that name outlives self
{
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}
Well you need to give borrow checker a way to infer the lifetimes. What's essentially missing is one of the following line
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some(Element(self.name))
}
}
into fn name(&mut self) -> Option<Element<'a>>. The Rust borrow checker will take care of the rest [Playground link].
Compiler seems smart enough to infer 'a should outlive 'self.

Cannot infer an appropriate lifetime due to conflicting requirements in a recursive struct

When I try to compile this code:
pub struct Context<'a> {
pub outer: Option<&'a mut Context<'a>>,
}
impl<'a> Context<'a> {
pub fn inside(outer: &'a mut Context) -> Context<'a> {
Context { outer: Some(outer) }
}
}
I'm getting this error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:7:9
|
7 | Context { outer: Some(outer) }
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 5:1...
--> src/main.rs:5:1
|
5 | / impl<'a> Context<'a> {
6 | | pub fn inside(outer: &'a mut Context) -> Context<'a> {
7 | | Context { outer: Some(outer) }
8 | | }
9 | | }
| |_^
note: ...so that expression is assignable (expected Context<'a>, found Context<'_>)
--> src/main.rs:7:9
|
7 | Context { outer: Some(outer) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / pub fn inside(outer: &'a mut Context) -> Context<'a> {
7 | | Context { outer: Some(outer) }
8 | | }
| |_____^
note: ...so that expression is assignable (expected &mut Context<'_>, found &mut Context<'_>)
--> src/main.rs:7:31
|
7 | Context { outer: Some(outer) }
| ^^^^^
Why this is happening?
This is because you haven't met the obligations that you require.
Due to lifetime elision, your code is equivalent to:
pub fn inside<'b>(outer: &'a mut Context<'b>) -> Context<'a>
Change your code to
pub fn inside(outer: &'a mut Context<'a>) -> Context<'a>
And it will compile.

Resources