Skip to content

Confusing errors when using Self variants with lifetimes #69224

New issue

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

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

Already on GitHub? # to your account

Open
clarfonthey opened this issue Feb 17, 2020 · 4 comments
Open

Confusing errors when using Self variants with lifetimes #69224

clarfonthey opened this issue Feb 17, 2020 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@clarfonthey
Copy link
Contributor

clarfonthey commented Feb 17, 2020

Minimal example, imagine that we have the following type:

enum MyCow<'a> {
    Owned(String),
    Borrowed(&'a str),
}

If the user returns Self variants, this fails:

impl<'a> MyCow<'a> {
    fn borrow(&self) -> MyCow<'_> {
        match self {
            Self::Owned(s) => Self::Borrowed(s),
            Self::Borrowed(s) => Self::Borrowed(s),
        }
    }
    fn own(&self) -> MyCow<'static> {
        match self {
            Self::Owned(s) => Self::Owned(s.clone()),
            Self::Borrowed(s) => Self::Owned(s.to_string()),
        }
    }
}

But the same code works when you change Self to MyCow!

impl<'a> MyCow<'a> {
    fn borrow(&self) -> MyCow<'_> {
        match self {
            Self::Owned(s) => MyCow::Borrowed(s),
            Self::Borrowed(s) => MyCow::Borrowed(s),
        }
    }
    fn own(&self) -> MyCow<'static> {
        match self {
            Self::Owned(s) => MyCow::Owned(s.clone()),
            Self::Borrowed(s) => MyCow::Owned(s.to_string()),
        }
    }
}

The real error here is that Self really represents MyCow<'a> and not MyCow<'_> or MyCow<'static>-, but the errors don't really relay this. Potentially linked issue: #30904 (has been fixed).

@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 17, 2020
@estebank estebank added the D-confusing Diagnostics: Confusing error or lint that should be reworked. label Jul 1, 2020
@clarfonthey
Copy link
Contributor Author

FWIW this is still an issue on the latest stable: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c6da051f190e76b03a995df938a86f2c

Also potentially related to #86555, even though the two are not technically the same. We could potentially just allow the version that uses Self here.

@RodBurman
Copy link

RodBurman commented Feb 13, 2025

Tool-chain version:

% cargo -v -V  
cargo 1.84.1 (66221abde 2024-11-19)
release: 1.84.1
commit-hash: 66221abdeca2002d318fde6efff516aab091df0e
commit-date: 2024-11-19
host: aarch64-apple-darwin
libgit2: 1.8.1 (sys:0.19.0 vendored)
libcurl: 8.7.1 (sys:0.4.74+curl-8.9.0 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: Mac OS 15.3.1 [64-bit]

Gives (with the self variant):

% vi src/lib.rs
rod@Mac confself % cargo build  
   Compiling confself v0.1.0 (/Users/rod/code/rust/triage/confself)
error: lifetime may not live long enough
  --> src/lib.rs:11:25
   |
8  | impl<'a> MyCow<'a> {
   |      -- lifetime `'a` defined here
9  |     fn borrow(&self) -> MyCow<'_> {
   |               - let's call the lifetime of this reference `'1`
10 |         match self {
11 |             Self::Owned(s) => Self::Borrowed(s),
   |                         ^ assignment requires that `'1` must outlive `'a`

error: lifetime may not live long enough
  --> src/lib.rs:17:31
   |
8  | impl<'a> MyCow<'a> {
   |      -- lifetime `'a` defined here
...
17 |             Self::Owned(s) => Self::Owned(s.clone()),
   |                               ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`

error: could not compile `confself` (lib) due to 2 previous errors

Is it agreed that this sufficiently explains the lifetimes' issue?

@clarfonthey
Copy link
Contributor Author

Honestly? Not really; the key is clarifying that Self is an alias for MyCow<'a> and not MyCow<'_>, and that's not clarified anywhere. The solution could even propose a fix to rename Self to the type in question.

@RodBurman
Copy link

RodBurman commented Feb 13, 2025

Agreed, my apologies I didn't read/study things thoroughly enough.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants