Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Implementing ToOwned ('a -> 'static) for an enum containing Cow<'a, str> causes unmet lifetime requirement

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading