Skip to content

Missing implied bound raises misleading error message #127900

Closed as duplicate

Description

@x4exr

I tried this code:

struct Foo<'a, T>(&'a T);

impl<'a, T> Foo<'a, T> {
    const X: usize = 100;
    
    fn what() {
        let a = [0; Self::X];
    }
}

I expected to see this happen: There should not be an error, the constant should have been evaluated as a literal. Using a literal does not raise the error.

Instead, this happened: Compile time error stating there is a lifetime issue. It requests a bound that shouldn't be neccessary. The error is misleading.

Meta

The bug occurs in my version and the latest stable.

rustc --version --verbose:

rustc 1.81.0-nightly (bcf94dec5 2024-06-23)
binary: rustc
commit-hash: bcf94dec5ba6838e435902120c0384c360126a26
commit-date: 2024-06-23
host: x86_64-pc-windows-msvc
release: 1.81.0-nightly
LLVM version: 18.1.7

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 18, 2024
  2. tgross35 commented on Jul 18, 2024

    @tgross35
    Member

    Error

       Compiling playground v0.0.1 (/playground)
    error[E0309]: the parameter type `T` may not live long enough
     --> src/lib.rs:7:21
      |
    3 | impl<'a, T> Foo<'a, T> {
      |      -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
    ...
    7 |         let a = [0; Self::X];
      |                     ^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
      |
    help: consider adding an explicit lifetime bound
      |
    3 | impl<'a, T: 'a> Foo<'a, T> {
      |           ++++
    
    For more information about this error, try `rustc --explain E0309`.
    error: could not compile `playground` (lib) due to 1 previous error
    

    Playground https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=200ea30e9ca44266eca4d5aba898794f

  3. tgross35 commented on Jul 18, 2024

    @tgross35
    Member

    This is confusing but I don't think it is a bug, I am sure there is an open issue for it somewhere...

    Maybe we could improve the diagnostics at least to explain "so that the type T will meet its required lifetime bounds" (what required lifetime bounds?).

  4. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    A-lifetimesArea: Lifetimes / regions
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 18, 2024
  5. fmease commented on Jul 18, 2024

    @fmease
    Member

    Pretty sure the underlying bug is #105495 (implied bounds from impl header are not used when checking assoc items for well-formedness)

  6. estebank commented on Jul 23, 2024

    @estebank
    Contributor
  7. fmease commented on Jul 23, 2024

    @fmease
    Member

    Note that explicit bounds in the type are also not accounted for in the impl.

    Right, but that's immaterial. It's not super relevant if the implied bound stems from an inferred or explicit outlives-bound (check_inferred_predicates vs. check_explicit_predicates). With implied bounds from impl header I'm referring to the implicit T: 'a inferred from the impl self type Foo<'a, T>. inferred_outlives_of(`Foo`) will contain T: 'a no matter what (&'a T implies T: 'a and so does <T: 'a>).

  8. fmease commented on Jul 23, 2024

    @fmease
    Member

    OTOH, turning the implied bound into an explicit bound in the impl header (as opposed to updating Foo's definition) does make a difference for obvious reasons:

    - impl<'a, T> Foo<'a, T> {
    + impl<'a, T: 'a> Foo<'a, T> {
  9. x4exr commented on Jul 23, 2024

    @x4exr
    ContributorAuthor

    I'm not sure if that really makes sense usage wise, shouldn't a constant have a static lifetime anyway?

  10. fmease commented on Dec 29, 2024

    @fmease
    Member

    I'm not sure if that really makes sense usage wise, shouldn't a constant have a static lifetime anyway?

    Nope, associated constants can have non-static lifetimes. Not the actual value/data I guess but you must still satisfy all lifetime outlives-bounds when referencing the associated item. I'm not entirely sure but I think that modifying the type system to allow lifetime-widening for Ty::<'a>::C from type &'a str to &'static str in fn f<'a>() { … } where impl<'a> Ty<'a> { const C: &'a str = ""; } can indirectly lead to unsoundness by allowing you to write a program that tricks rustc into accepting a general fn transmute<'a>(&'a str) -> &'static str via a series of intermediate stops (involving associated types and traits I assume). Then again, I could be totally wrong.

  11. fmease commented on Dec 29, 2024

    @fmease
    Member

    Anyway, I found an older issue that reports the very same issue. Closing in favor of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsD-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions