Values does not live long enough in constructor and setter in OOP Rust - oop

I have the following code:
//! # Messages
/// Represents a simple text message.
pub struct SimpleMessage<'a> {
pub user: &'a str,
pub content: &'a str,
}
impl<'a> SimpleMessage<'a> {
/// Creates a new SimpleMessage.
fn new_msg(u: &'a str, c: &'a str) -> SimpleMessage<'a> {
SimpleMessage { user: u,
content: &c.to_string(), }
}
/// Sets a User in a Message.
pub fn set_user(&mut self, u: User<'a>){
self.user = &u;
}
}
But $ cargo run returns:
error[E0597]: borrowed value does not live long enough
--> src/messages.rs:34:35
|
34 | content: &c.to_string(), }
| ^^^^^^^^^^^^^ temporary value does not live long enough
35 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 28:1...
|
28 | impl<'a> SimpleMessage<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0597]: `u` does not live long enough
|
54 | self.user = &u;
| ^ borrowed value does not live long enough
55 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 28:1...
--> src/messages.rs:28:1
|
28 | impl<'a> SimpleMessage<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
I've tried changing the borrowing format of the variables at the function signature and it's contents with no success, it doesn't seem as a borrowing issue, but I don't really understand it, as the lifetime <'a> defined at pub struct SimpleMessage<'a> clearly designates the longest lifetime to it's components, and the impl<'a> SimpleMessage<'a> uses the same lifetime.
What am I missing?
Similar Question:
“borrowed value does not live long enough” when using the builder pattern
Doesn't really help resolve this issue.

str.to_string() will create an owned String, which will not live longer than the new_msg method, so you will not be able to pass a slice of it anywhere. Instead, just use the &str argument, since it is valid for the lifetime 'a, which is what you need.
/// Creates a new SimpleMessage.
fn new_msg(u: &'a User, c: &'a str) -> SimpleMessage<'a> {
SimpleMessage { user: u, content: c, }
}
The other method also has a problem. You are trying to give an owned User, but the SimpleMessage struct requires a reference. It should look like this:
/// Sets a User in a Message.
pub fn set_user(&mut self, u: &'a User<'a>){
self.user = u;
}

You don't need to_string if you want to store a reference to a string. Also, set_user must also take a reference, not a value (because there's no field in the struct to store it):
pub struct User<'a> {
pub data: &'a u8,
}
/// Represents a simple text message.
pub struct SimpleMessage<'a> {
pub user: &'a User<'a>,
pub content: &'a str,
}
impl<'a> SimpleMessage<'a> {
fn new_msg(user: &'a User, content: &'a str) -> SimpleMessage<'a> {
SimpleMessage { user, content }
}
pub fn set_user(&mut self, user: &'a User<'a>) {
self.user = user;
}
}
fn main() {
let data1 = 1;
let data2 = 2;
let user1 = User { data: &data1 };
let user2 = User { data: &data2 };
let mut msg = SimpleMessage::new_msg(&user1, "test");
msg.set_user(&user2);
}
Playground
If you want to save strings that are created at runtime (for example, with format!() call) you may want to store a String:
pub struct SimpleMessage<'a> {
pub user: &'a User<'a>,
pub content: String,
}
. . .
fn new_msg(user: &'a User, content: String) -> SimpleMessage<'a> {
SimpleMessage { user, content }
}
. . .
let mut msg = SimpleMessage::new_msg(&user1, format!("created at {}", "runtime"));
Playground

Related

Support errors with lifetimes to have a source

I have the following 3 errors, AError, BError and CError, where CError contains a borrowed string from some input, and AError is composed from either BError or CError, and thus has a lifetime too.
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum AError<'a> {
B(BError),
C(CError<'a>),
}
impl<'a> fmt::Display for AError<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "AError")
}
}
impl<'a> Error for AError<'a> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
AError::B(err) => Some(err),
AError::C(_) => None, // If I try to use `C(err) => Some(err)` it errors
}
}
}
#[derive(Debug)]
pub struct BError;
impl fmt::Display for BError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BError")
}
}
impl Error for BError {}
#[derive(Debug)]
pub struct CError<'a> {
c: &'a str,
}
impl<'a> fmt::Display for CError<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CError: {}", self.c)
}
}
impl<'a> Error for CError<'a> {}
If I try to make A return C as a source error, I get the following error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:18:15
|
18 | match self {
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 16:6...
--> src/lib.rs:16:6
|
16 | impl<'a> Error for AError<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:18:15
|
18 | match self {
| ^^^^
= note: expected `&AError<'_>`
found `&AError<'a>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src/lib.rs:18:9
|
18 | / match self {
19 | | AError::B(err) => Some(err),
20 | | AError::C(err) => Some(err),
21 | | }
| |_________^
= note: expected `Option<&(dyn std::error::Error + 'static)>`
found `Option<&dyn std::error::Error>`
Which makes sense as source is declared with fn source(&self) -> Option<&(dyn Error + 'static)>.
I understand in order to be able to downcast, you must have a static reference, but all I want to do with it is print a backtrace of errors using source as such:
pub fn fmt_err(err: &dyn Error, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "{}", err)?;
if let Some(source) = err.source() {
fmt_err(source, f)?;
}
Ok(())
}
which doesn't require downcasting, simply uses the fact that fmt::Display is a super-trait of Error.
How can I make my errors with lifetimes support this type of usecase?
I know Error::cause exists, but it is deprecated and likely not intended for this use case and popular error deriving libraries (such as thiserror) likely don't implement it either, so I have to make do with source as my only way of getting an underlying error.
Is my only option to make my own trait and implement it for any errors with lifetimes?

Serde serialize with proxy type for remote object

How can I create a serializer proxy object for a remote type with Serde? Here is a minimal example (playground):
use serde; // 1.0.104
use serde_json; // 1.0.48
struct Foo {
bar: u8,
}
impl Foo {
pub fn new() -> Self {
Foo { bar: 10 }
}
pub fn val(&self) -> u8 {
self.bar
}
}
#[derive(serde::Serialize)]
#[serde(remote = "Foo")]
struct Bar {
#[serde(getter = "Foo::val")]
val: u8,
}
fn main() {
let foo = Foo::new();
let res = serde_json::to_string(&foo).unwrap();
println!("{}", res);
}
It cannot find the implementation:
error[E0277]: the trait bound `Foo: _IMPL_SERIALIZE_FOR_Bar::_serde::Serialize` is not satisfied
--> src/main.rs:27:37
|
27 | let res = serde_json::to_string(&foo).unwrap();
| ^^^^ the trait `_IMPL_SERIALIZE_FOR_Bar::_serde::Serialize` is not implemented for `Foo`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.48/src/ser.rs:2233:8
|
2233 | T: Serialize,
| --------- required by this bound in `serde_json::ser::to_string`
#[serde(remote = "Foo")] cannot break the orphan rule so does not really implement the trait for the type Foo.
You must use it with #[serde(with = "...")].
An easy way to do this is to create a small wrapper for serialization:
#[derive(serde::Serialize)]
struct FooWrapper<'a>(#[serde(with = "Bar")] &'a Foo);
and use it as serde_json::to_string(&FooWrapper(&foo)) (permalink to the playground).
This will serialize Foo as you expect using the remote definition Bar.
For deserialization, you can use Bar::deserialize and you will get a Foo directly.
See also:
serde's documentation: Deriving De/Serialize for type in a different crate

Lifetime inference problem when implementing iterator with refs

I'm implementing a simple Iterator for a struct that contains a ref:
extern crate zip;
extern crate quick_xml;
extern crate chrono;
use std::io::{Seek, Write, Read, Error};
use std::fs::File;
use xlsx_read::zip::read::ZipFile;
use xlsx_read::zip::result::ZipResult;
use xlsx_read::zip::ZipArchive;
use xlsx_read::zip::write::{FileOptions, ZipWriter};
use xlsx_read::quick_xml::Reader as XmlReader;
use xlsx_read::quick_xml::events::Event;
use std::io::BufReader;
use xlsx_read::chrono::prelude::*;
pub struct XlsxFile<'a> {
path: &'a str,
archive: ZipArchive<File>,
sheet_count: usize,
curr: usize,
}
impl<'a> XlsxFile<'a> {
pub fn from(path: &'a str) -> Result<XlsxFile, Error> {
let file = File::open(path)?;
let archive = ZipArchive::new(file)?;
let sheet_count = archive.len();
Ok(XlsxFile {
path: path,
archive: archive,
sheet_count,
curr: 0,
})
}
}
pub struct XlsxSheet<'a> {
pub name: &'a str,
pub index: usize,
}
impl<'a> Iterator for XlsxFile<'a> {
type Item = XlsxSheet<'a>;
fn next(&mut self) -> Option<XlsxSheet<'a>> {
loop {
if self.sheet_count > 0 &&
self.sheet_count > self.curr {
let zip_file = self.archive.by_index(self.curr).unwrap();
let file_name = zip_file.name();
if file_name.contains("xl/worksheets/sheet") {
let sheet = XlsxSheet {
name: file_name, // works fine if String::from(file_name) is used
index: self.curr,
};
self.curr += 1;
return Some(sheet);
}
self.curr += 1;
continue;
} else {
break;
}
}
return None;
}
}
static XLSX_FILE: &'static str = "<location_to_xlsx_file>";
fn main() {
let mut file = xlsx_read::XlsxFile::from(XLSX_FILE).unwrap();
file.for_each(|s| println!("idx: {:?}", s.name));
}
But I get the following error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/xlsx_read.rs:50:45
|
50 | let zip_file = self.archive.by_index(self.curr).unwrap();
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 46:5...
--> src/xlsx_read.rs:46:5
|
46 | / fn next(&mut self) -> Option<XlsxSheet<'a>> {
47 | | loop {
48 | | if self.sheet_count > 0 &&
49 | | self.sheet_count > self.curr {
... |
66 | | return None;
67 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/xlsx_read.rs:50:32
|
50 | let zip_file = self.archive.by_index(self.curr).unwrap();
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 43:1...
--> src/xlsx_read.rs:43:1
|
43 | impl<'a> Iterator for XlsxFile<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
expected std::option::Option<xlsx_read::XlsxSheet<'a>>
found std::option::Option<xlsx_read::XlsxSheet<'_>>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
My question is, how to tell Rust compiler to use appropriate lifetime here? Even though I've defined XlsxSheet<'a> with lifetime modifier and want to tie name to &'a str but somehow this doesn't translate into a valid Rust code.
Easy Solution: This problem can be trivially fixed by using String instead of &'a str.
Explanation:
I don't know the definition of by_index, which seems to be quite crucial to this problem. The following reasoning is pure guess and it's not reliable. It's offered only for reference.
self.archive borrows self (which is valid over the entire scope, let's say the lifetime is named 'me), and has lifetime 'me.
Thus the return value of by_index has lifetime 'me.
Oops, XlsxSheet<'me> is not compatible with XlsxSheet<'a> (which is expected)!
What we want here is XlsxSheet<'me> being a subtype of XlsxSheet<'a>, which in turn implies 'me being a subtype of 'a, if XlsxSheet is covariant. Therefore, you can state them explicitly
fn next(&mut self) -> Option<XlsxSheet<'a>> where Self: 'a
// or
impl<'a> Iterator for XlsxFile<'a> + 'a

Type mismatch resolving iterator Item to a pointer with an explicit lifetime

I'm trying to add functions to Iterator where the associated type Item is a reference to a struct with an explicit lifetime.
When I've wanted to modify the iterator state or return a new value I've had no problems, but when I attempt to return a new Iterator where Item is a reference with an explicit lifetime, the compiler complains.
Example
use std::marker::PhantomData;
/// First, an "Inner" struct to be contained in my custom iterator
pub struct Inner {
text: String,
}
/// Then, the "CustomIterator" in question. Notice that `Item` is `&'a Inner`.
pub struct CustomIterator<'a, I: Iterator<Item = &'a Inner>> {
iter: I,
_marker: PhantomData<&'a i8>,
}
/// Implementing Iterator for CustomIterator so as to define the `next()` function, as you do...
impl<'a, I: Iterator<Item = &'a Inner>> Iterator for CustomIterator<'a, I> {
type Item = &'a Inner;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
/// Now, creating a custom trait definition called IterateMore that:
/// 1. inherits Iterator
/// 2. includes a default method called `more` which returns a `CustomIterator`
pub trait IterateMore<'a>: Iterator {
type Item;
fn more(self) -> CustomIterator<'a, Self>
where
Self: Sized;
}
/// Implementing `IterateMore` for an iterator of the specific type `Iterator<Item=&'a Inner>`
impl<'a, I: Iterator<Item = &'a Inner>> IterateMore<'a> for I
where
I: Iterator,
{
type Item = &'a Inner;
fn more(self) -> CustomIterator<'a, Self>
where
Self: Sized,
{
CustomIterator {
iter: self,
_marker: PhantomData,
}
}
}
fn main() {
let inner = Inner {
text: "Hello world".to_string(),
};
let inners = vec![&inner];
inners.iter().more().next();
}
(See it on repl.it)
Error
error[E0271]: type mismatch resolving `<Self as std::iter::Iterator>::Item == &'a Inner`
--> src/main.rs:28:5
|
28 | / fn more(self) -> CustomIterator<'a, Self>
29 | | where
30 | | Self: Sized;
| |____________________^ expected associated type, found reference
|
= note: expected type `<Self as std::iter::Iterator>::Item`
found type `&'a Inner`
= note: required by `CustomIterator`
Why is Item not being resolved here? It is a bit frustrating as the compiler also complains if I try to set &'a Inner as the default Item type in the trait definition, saying:
error: associated type defaults are unstable (see issue #29661)
How could this be fixed or done differently?
It is unclear to me why you'd want to restrict the wrapped iterator to some custom type (given that you still have to write down the restriction every time you use the type, although that might change). But perhaps your "real" next function does something funny.
PhantomData doesn't seem to be necessary (anymore) to "use" the lifetime when it is used in a where-clause.
IterateMore shouldn't have an Item associated type, given Iterator already has it. (If you'd really need a new type pick a different name)
As IterateMore uses the CustomIterator type it needs to repeat the requirements, in this case Iterator<Item = &'a Inner> (that is what the type mismatch error is about); this is not the same as saying type Item = &'a Inner in the trait definition.
Playground
/// an "Inner" struct to be contained in my custom iterator
pub struct Inner {
text: String,
}
pub struct CustomIterator<'a, I>
where
I: Iterator<Item = &'a Inner>,
{
iter: I,
}
impl<'a, I> Iterator for CustomIterator<'a, I>
where
I: Iterator<Item = &'a Inner>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
pub trait IterateMore<'a>: Iterator<Item = &'a Inner> + Sized {
fn more(self) -> CustomIterator<'a, Self>;
}
impl<'a, I> IterateMore<'a> for I
where
I: Iterator<Item = &'a Inner>,
{
fn more(self) -> CustomIterator<'a, Self> {
CustomIterator { iter: self }
}
}
fn main() {
let inner = Inner {
text: "Hello world".to_string(),
};
let inners = vec![inner];
inners.iter().more().next();
}
You could also remove the type restrictions everywhere like this (and only add it back in the place you actually need/want it):
Playground
pub struct CustomIterator<I> {
iter: I,
}
impl<I> Iterator for CustomIterator<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
println!("Custom next called");
self.iter.next()
}
}
pub trait IterateMore: Iterator + Sized {
fn more(self) -> CustomIterator<Self>;
}
impl<I> IterateMore for I
where
I: Iterator,
{
fn more(self) -> CustomIterator<Self>
{
CustomIterator { iter: self }
}
}
fn main() {
let inners = vec!["Hello world".to_string()];
inners.iter().more().next();
}

How can we write a generic function for checking Serde serialization and deserialization?

In a project where custom Serde (1.0) serialization and deserialization methods are involved, I have relied on this test routine to check whether serializing an object and back would yield an equivalent object.
// let o: T = ...;
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
Doing this inline works pretty well. My next step towards reusability was to make a function check_serde for this purpose.
pub fn check_serde<T>(o: T)
where
T: Debug + PartialEq<T> + Serialize + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
This works well for owning types, but not for types with lifetime bounds (Playground):
check_serde(5);
check_serde(vec![1, 2, 5]);
check_serde("five".to_string());
check_serde("wait"); // [E0279]
The error:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:24:5
|
24 | check_serde("wait"); // [E0277]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `&str`
= note: required by `check_serde`
As I wish to make the function work with these cases (including structs with string slices), I attempted a new version with an explicit object deserialization lifetime:
pub fn check_serde<'a, T>(o: &'a T)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
let buf: Vec<u8> = to_vec(o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde(&"wait"); // [E0405]
This implementation leads to another issue, and it won't compile (Playground).
error[E0597]: `buf` does not live long enough
--> src/main.rs:14:29
|
14 | let o2: T = from_slice(&buf).unwrap();
| ^^^ does not live long enough
15 | assert_eq!(o, &o2);
16 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 10:1...
--> src/main.rs:10:1
|
10 | / pub fn check_serde<'a, T>(o: &'a T)
11 | | where T: Debug + PartialEq<T> + Serialize + Deserialize<'a>
12 | | {
13 | | let buf: Vec<u8> = to_vec(o).unwrap();
14 | | let o2: T = from_slice(&buf).unwrap();
15 | | assert_eq!(o, &o2);
16 | | }
| |_^
I have already expected this one: this version implies that the serialized content (and so the deserialized object) lives as long as the input object, which is not true. The buffer is only meant to live as long as the function's scope.
My third attempt seeks to build owned versions of the original input, thus evading the issue of having a deserialized object with different lifetime boundaries. The ToOwned trait appears to suit this use case.
pub fn check_serde<'a, T: ?Sized>(o: &'a T)
where
T: Debug + ToOwned + PartialEq<<T as ToOwned>::Owned> + Serialize,
<T as ToOwned>::Owned: Debug + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T::Owned = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
This makes the function work for plain string slices now, but not for composite objects containing them (Playground):
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde("wait");
check_serde(&("There's more!", 36)); // [E0279]
Again, we stumble upon the same error kind as the first version:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:25:5
|
25 | check_serde(&("There's more!", 36)); // [E0279]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `(&str, {integer})`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `(&str, {integer})`
= note: required by `check_serde`
Granted, I'm at a loss. How can we build a generic function that, using Serde, serializes an object and deserializes it back into a new object? In particular, can this function be made in Rust (stable or nightly), and if so, what adjustments to my implementation are missing?
Unfortunately, what you need is a feature that is not yet implemented in Rust: generic associated types.
Let's look at a different variant of check_serde:
pub fn check_serde<T>(o: T)
where
for<'a> T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde("wait"); // [E0279]
}
The problem here is that o2 cannot be of type T: o2 refers to buf, which is a local variable, but type parameters cannot be inferred to types constrained by a lifetime that is restricted to the function's body. We'd like for T to be something like &str without a specific lifetime attached to it.
With generic associated types, this could be solved with something like this (obviously I can't test it, since it's not implemented yet):
trait SerdeFamily {
type Member<'a>: Debug + for<'b> PartialEq<Self::Member<'b>> + Serialize + Deserialize<'a>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32; // ignoring a parameter is allowed
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
}
pub fn check_serde<'a, Family>(o: Family::Member<'a>)
where
Family: SerdeFamily,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
// `o2` is of type `Family::Member<'b>`
// with a lifetime 'b different from 'a
let o2: Family::Member = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
The answer from Francis Gagné has shown that we cannot do this efficiently without generic associated types. Establishing deep ownership of the deserialized object is a possible work-around which I describe here.
The third attempt is very close to a flexible solution, but it falls short due to how std::borrow::ToOwned works. The trait is not suitable for retrieving a deeply owned version of an object. Attempting to use the implementation of ToOwned for &str, for instance, gives you another string slice.
let a: &str = "hello";
let b: String = (&a).to_owned(); // expected String, got &str
Likewise, the Owned type for a struct containing string slices cannot be a struct containing Strings. In code:
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Foo<'a>(&str, i32);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FooOwned(String, i32);
We cannot impl ToOwned for Foo to provide FooOwned because:
If we derive Clone, the implementation of ToOwned for T: Clone is only applicable to Owned = Self.
Even with a custom implementation of ToOwned, the trait requires that the owned type can be borrowed into the original type (due to the constraint Owned: Borrow<Self>). That is, we are supposed to be able to retrieve a &Foo(&str, i32) out of a FooOwned, but their internal structure is different, and so this is not attainable.
This means that, in order to follow the third approach, we need a different trait. Let's have a new trait ToDeeplyOwned which turns an object into a fully owned one, with no slices or references involved.
pub trait ToDeeplyOwned {
type Owned;
fn to_deeply_owned(&self) -> Self::Owned;
}
The intent here is to produce a deep copy out of anything. There doesn't seem to be an easy catch-all implementation, but some tricks are possible. First, we can implement it to all reference types where T: ToDeeplyOwned.
impl<'a, T: ?Sized + ToDeeplyOwned> ToDeeplyOwned for &'a T {
type Owned = T::Owned;
fn to_deeply_owned(&self) -> Self::Owned {
(**self).to_deeply_owned()
}
}
At this point we would have to selectively implement it to non-reference types where we know it's ok. I wrote a macro for making this process less verbose, which uses to_owned() internally.
macro_rules! impl_deeply_owned {
($t: ty, $t2: ty) => { // turn $t into $t2
impl ToDeeplyOwned for $t {
type Owned = $t2;
fn to_deeply_owned(&self) -> Self::Owned {
self.to_owned()
}
}
};
($t: ty) => { // turn $t into itself, self-contained type
impl ToDeeplyOwned for $t {
type Owned = $t;
fn to_deeply_owned(&self) -> Self::Owned {
self.to_owned()
}
}
};
}
For the examples in the question to work, we need at least these:
impl_deeply_owned!(i32);
impl_deeply_owned!(String);
impl_deeply_owned!(Vec<i32>);
impl_deeply_owned!(str, String);
Once we implement the necessary traits on Foo/FooOwned and adapt serde_check to use the new trait, the code now compiles and runs successfully (Playground):
#[derive(Debug, PartialEq, Serialize)]
struct Foo<'a>(&'a str, i32);
#[derive(Debug, PartialEq, Clone, Deserialize)]
struct FooOwned(String, i32);
impl<'a> ToDeeplyOwned for Foo<'a> {
type Owned = FooOwned;
fn to_deeply_owned(&self) -> FooOwned {
FooOwned(self.0.to_string(), self.1)
}
}
impl<'a> PartialEq<FooOwned> for Foo<'a> {
fn eq(&self, o: &FooOwned) -> bool {
self.0 == o.0 && self.1 == o.1
}
}
pub fn check_serde<'a, T: ?Sized>(o: &'a T)
where
T: Debug + ToDeeplyOwned + PartialEq<<T as ToDeeplyOwned>::Owned> + Serialize,
<T as ToDeeplyOwned>::Owned: Debug + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T::Owned = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
// all of these are ok
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde("wait");
check_serde(&"wait");
check_serde(&Foo("There's more!", 36));
Update (04.09.2021):
The latest nightly has some fixes around GATs which basically allows the original example:
#![feature(generic_associated_types)]
use serde::{Deserialize, Serialize};
use serde_json::{from_slice, to_vec};
use std::fmt::Debug;
trait SerdeFamily {
type Member<'a>:
Debug +
for<'b> PartialEq<Self::Member<'b>> +
Serialize +
Deserialize<'a>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32;
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
}
fn check_serde<F: SerdeFamily>(o: F::Member<'_>) {
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: F::Member<'_> = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
The example above compiles now: playground.
As of now it's possible to implement this on rust nightly (with an explicit variance workaround):
#![feature(generic_associated_types)]
use serde::{Deserialize, Serialize};
use serde_json::{from_slice, to_vec};
use std::fmt::Debug;
trait SerdeFamily {
type Member<'a>: Debug + PartialEq + Serialize + Deserialize<'a>;
// https://internals.rust-lang.org/t/variance-of-lifetime-arguments-in-gats/14769/19
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short>;
}
struct I32Family;
struct StrFamily;
impl SerdeFamily for I32Family {
type Member<'a> = i32; // we can ignore parameters
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short> {
long
}
}
impl SerdeFamily for StrFamily {
type Member<'a> = &'a str;
fn upcast_gat<'short, 'long: 'short>(long: Self::Member<'long>) -> Self::Member<'short> {
long
}
}
fn check_serde<F: SerdeFamily>(o: F::Member<'_>) {
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: F::Member<'_> = from_slice(&buf).unwrap();
assert_eq!(F::upcast_gat(o), o2);
}
fn main() {
check_serde::<I32Family>(5);
check_serde::<StrFamily>("wait");
}
Playground
Simple (but a little awkward) solution: Provide buf from outside of the function.
pub fn check_serde<'a, T>(o: &'a T, buf: &'a mut Vec<u8>)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
*buf = to_vec(o).unwrap();
let o2: T = from_slice(buf).unwrap();
assert_eq!(o, &o2);
}
buf can be reused with Cursor
pub fn check_serde_with_cursor<'a, T>(o: &'a T, buf: &'a mut Vec<u8>)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
buf.clear();
let mut cursor = Cursor::new(buf);
to_writer(&mut cursor, o).unwrap();
let o2: T = from_slice(cursor.into_inner()).unwrap();
assert_eq!(o, &o2);
}