Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False positive "lifetime may not live long enough" with Cow, ToOwned and Sized #108345

Open
EqualMa opened this issue Feb 22, 2023 · 2 comments
Open
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@EqualMa
Copy link
Contributor

EqualMa commented Feb 22, 2023

I tried this code:

use std::borrow::Cow;

pub trait Trait {
    fn method(self) -> Cow<'static, str>
    where
        Self: Sized;
}

impl Trait for Cow<'_, str> {
    fn method(self) -> Cow<'static, str>
    where
        Self: Sized,
    {
        Cow::<'static, str>::Borrowed("")
    }
}

I expected to see this happen: it compiles.

Instead, this happened: lifetime may not live long enough

If I remove the where Self: Sized in both trait declaration and implementation, it compiles. However, in real world application, there are other methods in this trait so I have to add where Self: Sized to make the trait dyn-safe.

If I remove the where Self: Sized only in implementation, it compiles. However, If the return type is changed to Option<Cow<'static, str>>, the code would warn about impl method assumes more implied bounds than the corresponding trait method. I think this might be a bug.

use std::borrow::Cow;

pub trait Trait {
    fn method(self) -> Option<Cow<'static, str>>
    where
        Self: Sized;
}

impl Trait for Cow<'_, str> {
    fn method(self) -> Option<Cow<'static, str>> {
        None
    }
}

Meta

rustc --version --verbose:

rustc 1.67.1 (d5a82bbd2 2023-02-07)
binary: rustc
commit-hash: d5a82bbd26e1ad8b7401f6a718a9c57c96905483
commit-date: 2023-02-07
host: aarch64-apple-darwin
release: 1.67.1
LLVM version: 15.0.6
Backtrace

error: lifetime may not live long enough
  --> src/main.rs:14:9
   |
10 |     fn method(self) -> Cow<'static, str>
   |               ---- has type `Cow<'1, str>`
...
14 |         Cow::<'static, str>::Borrowed("")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ proving this value is `Sized` requires that `'1` must outlive `'static`

error: could not compile `my-test-2` due to previous error

@EqualMa EqualMa added the C-bug Category: This is a bug. label Feb 22, 2023
@wwylele
Copy link
Contributor

wwylele commented Feb 22, 2023

Interestingly, this seems to be related to the fact that both trait implementer type and return type are Cow<str> even though they have totally unrelated lifetime. If the return type is slightly changed, the code compiles

// this compiles
use std::borrow::Cow;

pub trait Trait {
    fn method(self) -> Cow<'static, [u8]>
    where
        Self: Sized;
}

impl Trait for Cow<'_, str> {
    fn method(self) -> Cow<'static, [u8]>
    where
        Self: Sized,
    {
        Cow::<'static, [u8]>::Borrowed(&[])
    }
}

@aliemjay
Copy link
Member

The root problem here is that trivial where clauses can impose surprising lifetime constraints:

use std::borrow::Cow;

fn test<'a>()
where
    Cow<'a, u8>: Sized,
{
    let _: Option<Cow<'static, u8>> = None;
    //~^ ERROR lifetime may not live long enough
    // requires 'a == 'static
}

It can even constrain inference in a surprising way:

use std::borrow::Cow;

fn test<'a>()
where
    Cow<'a, u8>: Sized,
{
    let _: Option<Cow<'_, _>> = None;
    //^ the type is inferred to be Option<Cow<'_, u8>>
}

@fmease fmease added A-lifetimes Area: Lifetimes / regions T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. and removed needs-triage-legacy labels Sep 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants