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

Missing implied bound raises misleading error message #127900

Open
x4exr opened this issue Jul 18, 2024 · 7 comments
Open

Missing implied bound raises misleading error message #127900

x4exr opened this issue Jul 18, 2024 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related 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

@x4exr
Copy link
Contributor

x4exr commented Jul 18, 2024

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
@x4exr x4exr added the C-bug Category: This is a bug. label Jul 18, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 18, 2024
@tgross35
Copy link
Contributor

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

@tgross35
Copy link
Contributor

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?).

@tgross35 tgross35 added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-confusing Diagnostics: Confusing error or lint that should be reworked. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jul 18, 2024
@fmease
Copy link
Member

fmease commented Jul 18, 2024

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

@estebank
Copy link
Contributor

@estebank estebank removed the C-bug Category: This is a bug. label Jul 23, 2024
@fmease
Copy link
Member

fmease commented Jul 23, 2024

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>).

@fmease
Copy link
Member

fmease commented Jul 23, 2024

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> {

@x4exr
Copy link
Contributor Author

x4exr commented Jul 23, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related 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

No branches or pull requests

5 participants