On the code below, I'm trying to transform a reference to owned data. The method to_owned ensures a 'static lifetime for the new returned type. However, it's complaining that this returned type is not really 'static because of the impl <'a>. I don't see what does 'a have to do with this since all the returned objects in to_owned are owned and thus should be 'static.
pub enum RRtspEncodedPacket<'a> {
Owned(Data<Body>),
Ref(&'a Data<Body>)
}
pub struct Body(Inner);
enum Inner {
Vec(Vec<u8>),
Custom(Box<dyn Custom>),
}
trait Custom: AsRef<[u8]> + Send + Sync + 'static {}
pub struct Data<Body> {
pub(crate) channel_id: u8,
pub(crate) body: Body,
}
pub trait EncodedPacket<'a, T: Send>: Send {
fn to_owned(&self) -> Box<dyn EncodedPacket<'static, T>>;
}
impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
fn to_owned(&self) -> Box<dyn EncodedPacket<'static, u8>> {
match self {
Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
Self::Ref(data) => Box::new(Self::Owned(*(*data).clone()))
}
}
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1eafce83690156b9df6432fd7092fec0
Error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/lib.rs:27:40
|
27 | Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
| ^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 24:6...
--> src/lib.rs:24:6
|
24 | impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:27:40
|
27 | Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
| ^^^^^^^^^^^
= note: expected `RRtspEncodedPacket<'_>`
found `RRtspEncodedPacket<'a>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src/lib.rs:27:31
|
27 | Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Box<(dyn EncodedPacket<'static, u8> + 'static)>`
found `Box<dyn EncodedPacket<'static, u8>>`
In to_owned() you are promising that you will return a Box<dyn EncodedPacket<'static, u8>>. But then you are using a Box<RRtspEncodedPacket<'a>> to construct the return value; the 'a may the shorter than 'static, which is what the compiler is complaining about. This is facilitated by the use of Self in Box::new(Self::Owned(*o.clone())). Here, Self refers to the type the impl block is for, so Self is RRtspEncodedPacket<'a>; this is how 'a sneaks into the return type. But what you want is RRtspEncodedPacket<'static>. Simply switching Self to RRtspEncodedPacket - which the compiler will infer to RRtspEncodedPacket<'static> - will solve your problem.
Reduced example that compiles:
pub enum RRtspEncodedPacket<'a> {
Owned(u32),
Ref(&'a u32)
}
pub trait EncodedPacket<'a, T> {
fn to_owned(&self) -> Box<dyn EncodedPacket<'static, T>>;
}
impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
fn to_owned(&self) -> Box<dyn EncodedPacket<'static, u8>> {
// Notice: No `Self`, because we go from whatever `Self` is
// (some `RRtspEncodedPacket<'a>` for some `'a`) to
// `RRtspEncodedPacket<'static>`.
match self {
Self::Owned(o) => Box::new(RRtspEncodedPacket::Owned(o.clone())),
Self::Ref(data) => Box::new(RRtspEncodedPacket::Owned((*data).clone()))
}
}
}
Related
I have a struct that wraps a std::cell::Ref and provides access by reference to the underlying value. Something like this:
use std::cell::Ref;
struct IntAccess<'a> {
i: Ref<'a, i32>,
}
impl IntAccess<'_> {
fn get(&self) -> &i32 {
&self.i
}
}
This works fine. Since I have multiple structs like this, I'd like to define a common trait:
trait Access {
type Item;
fn get(&self) -> Self::Item;
}
However, I get into trouble when trying to implement Access for IntAccess:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get(&self) -> Self::Item {
&self.i
}
}
It fails with the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:22:12
|
22 | fn get(&self) -> Self::Item {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:19:6
|
19 | impl<'a> Access for IntAccess<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:22:33
|
22 | fn get(&self) -> Self::Item {
| _________________________________^
23 | | &self.i
24 | | }
| |_____^
= note: expected `<IntAccess<'a> as Access>`
found `<IntAccess<'_> as Access>`
I think I kind of get what the compiler is trying to tell me: I'm trying to borrow self.i which has an anonymous lifetime unrelated to the lifetime of Self::Item ('a). So what seems to be needed is to somehow tie the lifetime of self in get to the lifetime 'a. Is there a way to do this?
I have to admit that I don't fully grasp the problem. Since I pass the lifetime 'a to the Ref, and Ref internally stores a reference with this lifetime, it seems to me that it should somehow be possible to get a reference with lifetime 'a out of it without having to explicitly tie self to this lifetime as well. So what am I missing here?
Your understanding is correct. About your doubt, let's name the lifetimes for easier debugging:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get<'b>(&'b self) -> Self::Item {
&self.i
}
}
self has the type &'b IntAccess<'a>. 'b is shorter than or equal to 'a - that is required for self to be well-formed, i.e. able to exist (otherwise, it would contain a dangling reference).
For that reason, we cannot borrow self for more than 'b - or we could do something like:
let v: IntAccess<'a>;
let inner: &'a i32 = {
let r: &'b IntAccess<'a> = &v;
<IntAccess<'a> as Access>::get(r)
}
let mut_r: &mut IntAccess<'a> = &mut v;
And we have both a shared and a mutable reference to (parts of) inner!
Your problem cannot be solved fully without Generic Associated Types. They allow you to parameterize an associated type by a lifetime, making it able to express "I want to return this associated type tied to the lifetime of self":
#![feature(generic_associated_types)]
trait Access {
type Item<'a>
where
Self: 'a;
fn get<'a>(&'a self) -> Self::Item<'a>;
// Or, with lifetime elision:
// fn get(&self) -> Self::Item<'_>;
}
impl<'a> Access for IntAccess<'a> {
type Item<'b> = &'b i32
where
'a: 'b;
fn get<'b>(&'b self) -> Self::Item<'b> {
&self.i
}
}
Playground.
Can we do that on stable? We can emulate that. Instead of implementing Access for IntAccess itself, we will implement it for a reference to it!
trait Access {
type Item;
fn get(self) -> Self::Item;
}
impl<'a, 'b> Access for &'b IntAccess<'a> {
type Item = &'b i32;
fn get(self) -> &'b i32 {
&self.i
}
}
Playground
This does not always work, and thus is not a full replacement to GATs, but is good enough in this case.
I have the following code:
pub trait Regex: RegexClone {
fn check(&self) -> Result<u32,(/* errors should detail where it fails*/)>;
fn next(&self) -> Option<Box<dyn Regex>>;
}
pub trait RegexClone {
fn regex_clone(&self) -> Box<dyn Regex>;
}
pub struct PatternAnyCharacter<'a>{
string: &'a str
}
impl RegexClone for PatternAnyCharacter<'_> {
fn regex_clone(&self) -> Box<dyn Regex> {
return Box::new(PatternAnyCharacter {string: self.string})
}
}
impl Regex for PatternAnyCharacter<'_> {
fn check(&self) -> Result<u32, ()> {
if self.string.len() > 0 {
return Ok(1);
}
Err(())
}
fn next(&self) -> Option<Box<dyn Regex>> {
None
}
}
The idea is that when i call regex_clone i get a new Box<dyn Regex> with the same &str as member, i supossed that since im only using inmutable references when calling regex_clone it would give me a new struct with the same string slice, since is a reference im not moving anything, however the compiler complains the following:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/lib.rs:63:25
|
63 | return Box::new(PatternAnyCharacter {string: self.string})
| ^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined here...
--> src/lib.rs:61:41
|
61 | impl RegexClone for PatternAnyCharacter<'_> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:63:54
|
63 | return Box::new(PatternAnyCharacter {string: self.string})
| ^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> src/lib.rs:63:16
|
63 | return Box::new(PatternAnyCharacter {string: self.string})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Box<(dyn Regex + 'static)>`
found `Box<dyn Regex>`
How can i solve this so i can share the same string slice with multiple struct?
i thought about foregoing the string slice as member entirely and passing it as parameter to check, but hopefully i can avoid it.
You need to define at the trait that the returned dyn Regex can't outlive &self if you want to allow it to borrow from parts of &self.:
pub trait RegexClone {
fn regex_clone<'a>(&'a self) -> Box<dyn Regex + 'a>;
}
(You can also use an anonymous lifetime (Box<dyn Regex + '_>), but this is easier to understand.)
Side note: I don't think "clone" is the right name for such a function.
I have some types like this, where they each have a lifetime parameter.
use std::marker::PhantomData;
use std::ops::Index;
pub struct Foo<'ctx> {
bars: Vec<Bar<'ctx>>,
phantom: PhantomData<&'ctx ()>,
}
impl Foo<'_> {
pub fn get_bar(&self, index: usize) -> Option<&Bar> {
self.bars.get(index)
}
}
pub struct Bar<'ctx> {
// pretend we are using a context here
phantom: PhantomData<&'ctx ()>,
}
I'd like to implement Index for Foo, but the compiler doesn't like it:
impl <'ctx> Index<usize> for Foo<'ctx> {
type Output = Bar<'ctx>;
fn index(&self, _index: usize) -> &Self::Output {
self.get_bar(_index).unwrap()
}
}
I get this error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/ir/foo.rs:24:14
|
24 | self.get_bar(_index).unwrap()
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/ir/foo.rs:23:14
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/ir/foo.rs:24:9
|
24 | self.get_bar(_index).unwrap()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'ctx` as defined here...
--> src/ir/foo.rs:20:7
|
20 | impl <'ctx> Index<usize> for Foo<'ctx> {
| ^^^^
note: ...so that the types are compatible
--> src/ir/foo.rs:23:53
|
23 | fn index(&self, _index: usize) -> &Self::Output {
| _____________________________________________________^
24 | | self.get_bar(_index).unwrap()
25 | | }
| |_____^
= note: expected `<Foo<'ctx> as Index<usize>>`
found `<Foo<'_> as Index<usize>>`
(I see a few similar questions on SO but they all seem to differ in the particulars, namely that the Output type has a lifetime parameter).
This is due to that the rust compiler cannot infer proper lifetimes when there are multiple elided lifetimes. The rust compiler can only take the omitted lifetimes as a same lifetime '_.
The inferred signature of the function get_bar is actually:
pub fn get_bar<'_>(self: &'_ Foo<'_>, index: usize) -> Option<&'_ Bar<'_>>
Note that all '_ refer to the same lifetime, this is obviously not what we need, because we don't have to keep borrowing the value of some Bar during the whole lifetime of 'ctx.
And, the inferred signature of the function index is:
fn index<'_>(self: &'_ Foo<'ctx>, _index: usize) -> &'_ Bar<'ctx>
Which is more generic than the signature of get_bar because it allows the lifetime argument of '_ to be shorter than 'ctx, therefore you cannot call get_bar within the body of index
To make it work, you have to specify an explicit 'ctx, because the elided lifetime '_ has to be the lifetime of the borrowed self.
impl<'ctx> Foo<'ctx> {
pub fn get_bar(&self, index: usize) -> Option<&Bar<'ctx>> {
self.bars.get(index)
}
}
And the signature of get_bar now turns to be:
pub fn get_bar<'_>(self: &'_ Foo<'ctx>, index: usize) -> Option<&'_ Bar<'ctx>>
Then the lifetimes in index could match the lifetimes in get_bar
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.
Consider the following code for a (greatly simplified) iterator with a reference to a closure inside:
struct IteratorState<'a, T: 'a + Fn(i32) -> i32> {
closure: &'a T,
}
impl<'a, T: 'a + Fn(i32) -> i32> Iterator for IteratorState<'a, T> {
type Item = i32;
fn next(&mut self) -> Option<i32> {
None
}
}
It compiles and I can construct IteratorStates directly. However, I also need a smart constructor to hide some details of the implementation (not shown in the MCVE). The following attempt does not compile:
fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
IteratorState { closure }
}
The error is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/lib.rs:14:5
|
14 | IteratorState { closure }
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:1...
--> src/lib.rs:13:1
|
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:14:21
|
14 | IteratorState { closure }
| ^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
--> src/lib.rs:13:54
|
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
I think I understand what the problem is: there's no guarantee that constructed IteratorState won't outlive the contained reference (please correct me if I got this wrong), but I'm not quite sure how to fix it.
The impl Trait syntax supports adding lifetimes to the return type:
fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> + 'a {
// here ^^^^
IteratorState {
closure
}
}
(link to playground)