Context
Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=de1286b8bce0dfb840a5fc0b50df25ad
I was reading this other SO post, which was saying you can convert a struct containing a Cow
to have a 'static
lifetime. Based on that post, I then tried the following:
use std::borrow::Cow;
enum S<'a> {
A(Cow<'a, str>),
B(i32)
}
impl ToOwned for S<'_> {
type Owned = S<'static>;
fn to_owned(&self) -> Self::Owned {
match *self {
S::A(s) => S::A(Cow::Owned(s.clone().into_owned())),
S::B(i) => S::B(i)
}
}
}
fn main() {
let s = S::A("a".into());
let s = s.to_owned();
}
and got the following error
error: incompatible lifetime on type
--> src/main.rs:9:18
|
9 | type Owned = S<'static>;
| ^^^^^^^^^^
|
note: because this has an unmet lifetime requirement
note: the lifetime `'_` as defined here...
--> src/main.rs:8:20
|
8 | impl ToOwned for S<'_> {
| ^^
note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
Questions
- How exactly are lifetimes coming into play here if I’m converting the
Cow
into the owned version? - What’s the right approach to getting this to work?
>Solution :
TL;DR: You cannot implement ToOwned
for that; use an inherent method.
ToOwned::Owned
has a bound:
type Owned: Borrow<Self>;
So we need S<'static>
to impl Borrow<S<'a>>
for any 'a
.
…except this impl cannot be written:
error[E0119]: conflicting implementations of trait `std::borrow::Borrow<S<'static>>` for type `S<'static>`
--> src/main.rs:19:1
|
19 | impl<'a> Borrow<S<'a>> for S<'static> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> Borrow<T> for T
where T: ?Sized;
…because it conflicts with the blanket implementation Borrow<T> for T
where 'a
is 'static
.
The compiler error without this impl is an outcome of the fact that the compiler sees that there is an impl<'a> Borrow<S<'a>> for S<'static>
(the abovementioned blanket implementation), it is just that it constrains 'a: 'static
. And so the compiler tries to prove 'a: 'static
, and fails. This is an example of the compiler being over-smart, causing a confusing error message.