object does not live long enough when implementing the `From` trait - rust

My code has a '... does not live long enough error' error when I implement the From<T> trait for FileSlice, because the FlieSlice reference to the argument of the from method, and the argument dropped when the method returned.
Is there some way the solve this problem? Thank you.
struct FileSlice {
data: Box<dyn FileHandle>,
}
trait FileHandle {
fn read(&self, range: Range<usize>);
}
impl FileHandle for &'static [u8] {
fn read(&self, range: Range<usize>) {
let a = &self[range];
println!("{:?}", a);
}
}
impl<T> From<T> for FileSlice
where
T: Deref<Target = [u8]> + 'static,
{
fn from(a: T) -> Self {
let b: &'static [u8] = a.deref(); //error: 'a' does not live long enough.
FileSlice { data: Box::new(b) }
}
}

Deref::deref() has the signature:
fn deref(&self) -> &Self::Target
Or, desugared:
fn deref<'a>(&'a self) -> &'a Self::Target
It borrows self, and returns a reference with the same lifetime. Because of that, if you want the resulting reference to be 'static, you need &self to be &'static self. T: 'static is not related: it means self is static, but &self is the address of the parameter a, which is obviously not 'static. What you need is:
impl<T> From<&'static T> for FileSlice
where
T: Deref<Target = [u8]>,
{
fn from(a: &'static T) -> Self {
let b: &'static [u8] = a.deref();
FileSlice { data: Box::new(b) }
}
}

Related

lifetime with closure captures in rust

How can I reduce the lifetime of a closure?
I was trying to make a method, which returns an iterator related to self. I didn't want to make new struct or something, so I just made it return filters and maps, and confronted some borrow checker errors.
The following code was my first try.
fn f<'b>(&'b self) -> impl Iterator<Item = u8> {
(0..self.some_number())
.filter(|&i| self.some_bool_function(i))
.map(|i| i as u8)
}
The following code replicates my question.
struct A(bool);
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(|&i| self.0)
}
}
or even shorter,
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
|| *t
}
This would not compile, because the closure may outlive self. I don't know how to make this work, without moving self.
If you return a closure, you must ensure that the closure has everything it needs - even after returning (i.e. after the (temporary) function parameters are popped from the stack).
Thus, I think you want to move the stuff you return into the closure:
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(move |&i| self.0)
}
}
Resp.
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
move || *t
}
Resp (extending your first example):
struct A(bool);
impl A {
fn some_number(&self) -> usize {
6
}
fn some_bool_function(&self, i: usize) -> bool {
i%2==0
}
fn f<'b>(&'b self) -> impl Iterator<Item = u8> + 'b {
(0..self.some_number())
.filter(move |&i| self.some_bool_function(i))
.map(|i| i as u8)
}
}

How can I implement a method to work with &str, Box<str>, Rc<str>, etc.?

I have code that transforms a string reference in some way, e.g. takes the first letter
trait Tr {
fn trim_indent(self) -> Self;
}
impl<'a> Tr for &'a str {
fn trim_indent(self) -> Self {
&self[..1] // some transformation here
}
}
fn main() {
let s = "aaa".trim_indent();
println!("{}", s);
}
Now I'm trying to generalize this code for any particular type that implements AsRef<str>. My final try was
use std::ops::Deref;
trait Tr<'a> {
fn trim_indent(self) -> Deref<Target = str> + 'a + Sized;
}
impl<'a, T: AsRef<str>> Tr<'a> for T {
fn trim_indent(self) -> Deref<Target = str> + 'a + Sized {
self.as_ref()[..1] // some transformation here
}
}
fn main() {
let s = "aaa".trim_indent();
println!("{}", s);
}
I'm stuck because without Sized I get an error that type is unknown at compile time, but with Size I get an error that I cannot use marker trait explicitly.
Regardless of what type you start with, the end type of slicing a &str is always a &str so your return type needs to be a &str.
Then it's a matter of implementing the trait for references to a type so that you can tie the input and output lifetimes together:
use std::rc::Rc;
trait Tr<'a> {
fn trim_indent(self) -> &'a str;
}
impl<'a, T> Tr<'a> for &'a T
where
T: AsRef<str> + 'a,
{
fn trim_indent(self) -> &'a str {
&self.as_ref()[..1] // Take the first **byte**
}
}
fn main() {
let s: &str = "aaa";
println!("{}", s.trim_indent());
let s: Box<str> = Box::from("bbb");
println!("{}", s.trim_indent());
let s: Rc<str> = Rc::from("ccc");
println!("{}", s.trim_indent());
}
In this case, since all the types you've listed implement Deref anyway, you can just implement the trait for &str and all of the types can use it:
trait Tr {
fn trim_indent(&self) -> &str;
}
impl Tr for str {
fn trim_indent(&self) -> &str {
&self[..1]
}
}
See also:
Why is capitalizing the first letter of a string so convoluted in Rust?

Trait method that can be implemented to either return a reference or an owned value

I'm trying to define a trait with a method that can be implemented to either return a reference or an owned value.
Something like:
struct Type;
trait Trait {
type Value;
fn f(&self) -> Self::Value;
}
impl Trait for () {
type Value = Type;
fn f(&self) -> Self::Value {
Type
}
}
impl Trait for (Type,) {
type Value = &Type; // error[E0106]: missing lifetime specifier
fn f(&self) -> Self::Value {
&self.0
}
}
This piece of code doesn't work though, since &Type is missing a lifetime specifier. I'd want &Type to have the same lifetime as &self (i.e. fn f<'a>(&'a self) -> &'a Type), but I don't know how to express this in Rust.
I managed to find a couple of ways to make this code work, but I don't love either of them:
Adding an explicit lifetime to the trait itself:
trait Trait<'a> {
type Value;
fn f<'b>(&'b self) -> Self::Value where 'b: 'a;
}
impl<'a> Trait<'a> for () {
type Value = Type;
fn f<'b>(&'b self) -> Self::Value
where 'b: 'a
{
Type
}
}
impl<'a> Trait<'a> for (Type,) {
type Value = &'a Type;
fn f<'b>(&'b self) -> Self::Value
where 'b: 'a
{
&self.0
}
}
What I don't like of this solution is that anything using Trait needs an explicit lifetime (which I believe is not intrinsically necessary), plus the trait seems unnecessarily complicated to implement.
Returning something that might or might not be a reference - like std::borrow::Cow:
trait Trait {
type Value;
fn f<'a>(&'a self) -> Cow<'a, Self::Value>;
}
impl Trait for () {
type Value = Type;
fn f<'a>(&'a self) -> Cow<'a, Self::Value> {
Cow::Owned(Type)
}
}
impl Trait for (Type,) {
type Value = Type;
fn f<'a>(&'a self) -> Cow<'a, Self::Value> {
Cow::Borrowed(&self.0)
}
}
What I don't like of this solution is that ().f() is a Cow<_>: I'd need to call ().f().into_owned() to obtain my Type. That seems unnecessary (and might result in some negligible run-time overhead when using Trait as a trait object).
Also note that Cow is not good since it requires that Self::Value implements ToOwned (thus, practically, Clone), which is too strong of a requirement. It's anyways easy to implement an alternative to Cow without such constraints.
Are there any other solutions to this problem? What's the standard/most common/preferred one?
This could be solved using an additional associated object to choose between whether to return a type or a reference, plus some meta-programming magic.
First, some helper types:
struct Value;
struct Reference;
trait ReturnKind<'a, T: ?Sized + 'a> {
type Type: ?Sized;
}
impl<'a, T: ?Sized + 'a> ReturnKind<'a, T> for Value {
type Type = T;
}
impl<'a, T: ?Sized + 'a> ReturnKind<'a, T> for Reference {
type Type = &'a T;
}
ReturnKind is a "type-level function" which returns T when the "input" is Value, and &T for Reference.
And then the trait:
trait Trait {
type Value;
type Return: for<'a> ReturnKind<'a, Self::Value>;
fn f<'a>(&'a self) -> <Self::Return as ReturnKind<'a, Self::Value>>::Type;
}
We produce the return type by "calling" the type-level function ReturnKind.
The "input argument" Return needs to implement the trait to allow us to write <Return as ReturnKind<'a, Value>>. Although we don't know what exactly the lifetime Self will be, we could make Return bound by all possible lifetime using HRTB Return: for<'a> ReturnKind<'a, Value>.
Usage:
impl Trait for () {
type Value = f64;
type Return = Value;
fn f(&self) -> f64 {
42.0
}
}
impl Trait for (f64,) {
type Value = f64;
type Return = Reference;
fn f(&self) -> &f64 {
&self.0
}
}
fn main() {
let a: (f64,) = ( ().f(), );
let b: &f64 = a.f();
println!("{:?} {:?}", a, b);
// (42,) 42
}
Note that the above only works when the Value type has 'static lifetime. If the Value itself has a limited lifetime, this lifetime has to be known by the Trait. Since Rust doesn't support associated lifetimes yet, it has to be used like Trait<'foo>, unfortunately:
struct Value;
struct Reference;
struct ExternalReference;
trait ReturnKind<'a, 's, T: ?Sized + 'a + 's> {
type Type: ?Sized;
}
impl<'a, 's, T: ?Sized + 'a + 's> ReturnKind<'a, 's, T> for Value {
type Type = T;
}
impl<'a, 's, T: ?Sized + 'a + 's> ReturnKind<'a, 's, T> for Reference {
type Type = &'a T;
}
impl<'a, 's, T: ?Sized + 'a + 's> ReturnKind<'a, 's, T> for ExternalReference {
type Type = &'s T;
}
trait Trait<'s> {
type Value: 's;
type Return: for<'a> ReturnKind<'a, 's, Self::Value>;
fn f<'a>(&'a self) -> <Self::Return as ReturnKind<'a, 's, Self::Value>>::Type;
}
impl Trait<'static> for () {
type Value = f64;
type Return = Value;
fn f(&self) -> f64 {
42.0
}
}
impl Trait<'static> for (f64,) {
type Value = f64;
type Return = Reference;
fn f(&self) -> &f64 {
&self.0
}
}
impl<'a> Trait<'a> for (&'a f64,) {
type Value = f64;
type Return = ExternalReference;
fn f(&self) -> &'a f64 {
self.0
}
}
fn main() {
let a: (f64,) = ( ().f(), );
let b: &f64 = a.f();
let c: &f64 = (b,).f();
println!("{:?} {:?} {:?}", a, b, c);
// (42,) 42 42
}
But if having the lifetime parameter on the trait is fine, then OP already provided an easier solution:
trait Trait<'a> {
type Value;
fn f<'b>(&'b self) -> Self::Value where 'b: 'a;
}
impl<'a> Trait<'a> for () {
type Value = f64;
fn f<'b: 'a>(&'b self) -> Self::Value {
42.0
}
}
impl<'a> Trait<'a> for (f64,) {
type Value = &'a f64;
fn f<'b: 'a>(&'b self) -> Self::Value {
&self.0
}
}
impl<'a, 's> Trait<'s> for (&'a f64,) {
type Value = &'a f64;
fn f<'b: 's>(&'b self) -> Self::Value {
self.0
}
}
fn main() {
let a: (f64,) = ( ().f(), );
let b: &f64 = a.f();
let c: &f64 = (b,).f();
println!("{:?} {:?} {:?}", a, b, c);
// (42,) 42 42
}
#kennytm presented an excellent (if complex) solution; I wish to propose a much simpler alternative.
There are two possibilities to provide the lifetime name for the value:
at the trait level: trait Trait<'a> { ... }
at the method level: trait Trait { fn f<'a>(&'a self) -> ... }
The latter is not well supported by the language, and while more flexible is also quite more complicated. However, it also happens that the former is often enough; and thus without ado I present you:
trait Trait<'a> {
type Value;
fn f(self) -> Self::Value;
}
f consumes its output, this is fine if Self is an immutable reference as those are Copy.
The proof is in the pudding:
struct Type;
impl Trait<'static> for () {
type Value = Type;
fn f(self) -> Self::Value {
Type
}
}
impl<'a> Trait<'a> for &'a (Type,) {
type Value = &'a Type;
fn f(self) -> Self::Value {
&self.0
}
}
And it can be invoked without issue:
fn main(){
().f();
(Type,).f();
}
This solution is certainly not as flexible; but it's also significantly simpler.

Trait to store structs with different generic parameters

I need to store in the same Vec instances of the same struct, but with different generic parameters. This is the struct definition:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
The struct has a method returning an iterator to a type that does not depend on the generic type parameter T:
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<&i32> {
unimplemented!()
}
}
I need to access this method for those different structs in the vector, so I've implemented this trait:
type Iter<'a> = Iterator<Item=&'a i32>;
trait Trait {
fn iter(&self) -> Box<Iter>;
}
And I've implemented the trait for Struct:
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> Box<Iter> {
Box::new(self.iter())
}
}
But the compiler complains:
<anon>:21:9: 21:30 error: type mismatch resolving `<core::slice::Iter<'_, &i32> as core::iter::Iterator>::Item == &i32`:
expected &-ptr,
found i32 [E0271]
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
<anon>:21:9: 21:30 help: see the detailed explanation for E0271
<anon>:21:9: 21:30 note: required for the cast to the object type `core::iter::Iterator<Item=&i32> + 'static`
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
I've tried different possibilities for lifetime parameters in the trait, but none of them work. How can I make this work?
Rust Playground snippet
Edit
As pointed out by #MatthieuM. one problem is that the type alias is not working properly. Here's another example demonstrating this:
use std::slice;
type Iter<'a> = Iterator<Item=&'a i32>;
struct Struct<'a> { _phantom: std::marker::PhantomData<&'a i32> }
impl<'a> Struct<'a> {
fn direct<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iterator<Item=&'a i32>
{ i }
fn aliased<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iter<'a>
{ i }
}
In this example, direct compiles, but aliased not, with the error:
<anon>:12:7: 12:8 error: the type `core::slice::Iter<'a, i32>` does not fulfill the required lifetime
<anon>:12 { i }
^
note: type must outlive the static lifetime
But they seem to be the same thing. What's happening?
Problem 1 — slice::Iter<T> has an Iterator::Item of &T, thus your reference levels are mismatched. Change your method to be
fn iter(&self) -> slice::Iter<i32>
Problem 2 — Box<SomeTrait> is equivalent to Box<SomeTrait + 'static>, but your iterator does not live for the 'static lifetime. You need to explicitly bring in a lifetime:
Box<SomeTrait + 'a>
Problem 3 — I don't understand how you can create a type alias for a trait, that seems very odd. You probably don't want it anyway. Instead, create a type alias for the whole boxed version:
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
Problem 4 — Rearrange your main so that references will live long enough and add mutability:
fn main() {
let i = 3;
let v = vec![&i];
let mut traits : Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct{ items: v }));
}
All together:
use std::slice;
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
trait Trait {
fn iter<'a>(&'a self) -> IterBox;
}
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<i32> {
unimplemented!()
}
}
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> IterBox {
Box::new(self.iter())
}
}
fn main() {
let i = 3;
let v = vec![&i];
let mut traits: Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct { items: v }));
}

Implementing Deref on a struct that owns a boxed trait

I'd like to implement Deref and DefrefMut on a struct that owns a boxed trait, e.g.:
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap {
value: Box<Quack>
}
impl Deref for QuackWrap {
type Target = Box<Quack>;
fn deref<'a>(&'a self) -> &'a Box<Quack> {
&self.value
}
}
impl DerefMut for QuackWrap {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> {
&mut self.value
}
}
This fails to compile with the following error:
src/main.rs:14:5: 16:6 error: method `deref` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053]
src/main.rs:14 fn deref<'a>(&'a self) -> &'a Box<Quack> {
src/main.rs:15 &self.value
src/main.rs:16 }
src/main.rs:20:5: 22:6 error: method `deref_mut` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053]
src/main.rs:20 fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> {
src/main.rs:21 &mut self.value
src/main.rs:22 }
If I replace Box<Quack> with Box<String> (or a similar type), it works. The problem is that Quack is a trait. But I'm not sure why that generated the error message it did. Any ideas?
My question is similar to another SO question, but not quite the same. In that question, the struct has a type parameter with the trait as a constraint. Whereas in my question, there is no type parameter.
I don't want to confuse the issues, but there's a good reason that I need Box<Quack> in my application. I.e. I can't replace Quack with a type parameter. In case you care, the reason is discussed further in another SO question.
When in doubt, add more lifetime annotations:
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap<'b> {
value: Box<Quack + 'b>
}
impl<'b> Deref for QuackWrap<'b>{
type Target = Box<Quack + 'b>;
fn deref<'a>(&'a self) -> &'a Box<Quack + 'b> {
&self.value
}
}
impl<'b> DerefMut for QuackWrap<'b> {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'b> {
&mut self.value
}
}
Based on Brian's answer and Shepmaster's explanation, I updated my code as follow. I also simplified the QuackWrap struct. (That wasn't strictly necessary, but it's arguably better style than what I was doing before.)
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap(Box<Quack>);
impl Deref for QuackWrap {
type Target = Box<Quack + 'static>;
fn deref<'a>(&'a self) -> &'a Box<Quack + 'static> {
let QuackWrap(ref v) = *self;
v
}
}
impl DerefMut for QuackWrap {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'static> {
let QuackWrap(ref mut v) = *self;
v
}
}
There may be a more concise way to destructure QuackWrap in the deref and deref_mut implementations. Some of those more obscure syntax rules elude me. But for now this is fine.

Resources