Skip to content

Missing variables/fields give confusing error when name is the same as a built-in attribute like start or path #86290

Closed

Description

@jjl

Given the following code:

struct Wat {
    start: (),
}
impl Wat {
    fn new() -> Wat {
      Wat { start }
    }
}

The current output is:

expected value, found built-in attribute `start`
a field by this name exists in `Self` [E0423]

I frankly have no idea what it's on about and I was surprised that it doesn't just tell me it can't find the variable of that name.

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 14, 2021
  2. mbartlett21 commented on Jun 15, 2021

    @mbartlett21
    Contributor

    This is because there is a builtin attribute #[start] that can be applied to a function to make it the entry point, which is what it resolves start to, since you have no variable shadowing it.

  3. jjl commented on Jun 17, 2021

    @jjl
    Author

    Ahh, gotcha. I don't think it's helpful to note that it found an attribute of that name, or at least it confused me.

  4. kpreid commented on Jul 23, 2022

    @kpreid
    Contributor

    If the field name does not happen to be an attribute, the note is less confusing but still unhelpful:

    struct Foo {
        bar: i32,
    }
    
    impl Foo {
        fn new() -> Self {
            Self {
                bar,
            }
        }
    }
    error[E0425]: cannot find value `bar` in this scope
     --> src/lib.rs:8:13
      |
    8 |             bar,
      |             ^^^ a field by this name exists in `Self`
    
    For more information about this error, try `rustc --explain E0425`.
    error: could not compile `playground` due to previous error
    

    It seems to me that there is little point in saying “a field by this name exists”, since we're in a struct initializer — if there wasn't such a field, we'd be getting a different error. Or perhaps it would be helpful to say “a field by this name exists in Self, but there is no variable by this name to initialize it with; try writing bar: something_else_here”.

  5. AnthonyMikh commented on Aug 14, 2022

    @AnthonyMikh
    Contributor

    Hit it today with a code that can be minified to this:

    fn f() {
        path
    }

    Giving

    error[E0423]: expected value, found built-in attribute `path`
     --> src/lib.rs:2:5
      |
    2 |     path
      |     ^^^^ not a value
    

    In my case it was even more confusing because I was rearranging my code and I actually had a variable named path, just in a nested scope.

    Interestingly enough, Rust prior to version 1.38.0 gives a more sensible error. For example, Rust 1.37.0 gives the following:

    error[E0425]: cannot find value `path` in this scope
     --> <source>:2:5
      |
    2 |     path
      |     ^^^^ not found in this scope
    
  6. added
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    D-papercutDiagnostics: An error or lint that needs small tweaks.
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    E-help-wantedCall for participation: Help is requested to fix this issue.
    on Jun 20, 2026
  7. clarfonthey commented on Jun 20, 2026

    @clarfonthey
    Contributor

    Want to call out that this is still happening in 2026: #158168 (comment)

  8. changed the title [-]Confusing error when populating a struct with a field called 'start' without an explicit value and a variable called start is not defined[/-] [+]Missing variables/fields give confusing error when name is the same as a built-in attribute like `start` or `path`[/+] on Jun 20, 2026
  9. TorinAsakura commented on Jul 14, 2026

    @TorinAsakura
    Contributor

    @rustbot claim

  10. petrochenkov commented on Jul 15, 2026

    @petrochenkov
    Contributor

    The logic of the diagnostic is that if we cannot find a name in its expected namespace, then we try to find it in the 2 remaining namespaces.

    We could also get something like "expected value, found enum E" or "expected value, found macro format" here.
    Why are built-in attributes specifically problematic in this case? How are they different from the cases above?
    I don't think we should change any logic here to special-case built-in attributes.
    Maybe only tweak the wording to make it clear that we are searching for the same name in different namespaces.

  11. TorinAsakura commented on Jul 16, 2026

    @TorinAsakura
    Contributor

    @petrochenkov and I concluded that this is worth discussing a bit more broadly:

    A possible wording for cross-namespace cases:

    • expected value, but a built-in attribute with the same name exists in another namespace
    • expected value, but an enum with the same name exists in another namespace
    • expected type, but a constant with the same name exists in another namespace

    Same-namespace diagnostics, error codes, labels, suggestions, and resolution order would stay unchanged. The diagnostic branch would be selected when res.ns() differs from source.namespace().

    Does this wording look reasonable?

  12. clarfonthey commented on Jul 16, 2026

    @clarfonthey
    Contributor

    I guess that part of the pause with respect to attributes is that it feels completely reasonable to accidentally use a type name, but since the attribute syntax requires so much extra wrapping, the attribute namespace feels totally unrelated. I would expect it to still say something along the lines of "name not defined (as a variable)" even if it mentions it found the attribute.

  13. TorinAsakura commented on Jul 16, 2026

    @TorinAsakura
    Contributor

    @clarfonthey Yeah, that distinction makes sense. The missing variable should stay front and center, and the attribute should only show up as extra context. Something like:

    • no value named path is defined in this scope
    • note: a built-in attribute named path exists in another namespace

    Then we can use the same shape for the other cross-namespace cases. Is that closer to what you had in mind?

  14. clarfonthey commented on Jul 16, 2026

    @clarfonthey
    Contributor

    Yes, except there should also be the usual "did you forget to define it?" caveat and the presence in another namespace shouldn't remove it.

  15. TorinAsakura commented on Jul 16, 2026

    @TorinAsakura
    Contributor

    @clarfonthey Got it. Then the cross-namespace lookup should be purely additive: keep the ordinary missing-name diagnostic and all of its suggestions, and only add a note about the name found in another namespace.

  16. added a commit that references this issue on Jul 21, 2026
    e1d8ba6
  17. added a commit that references this issue on Jul 21, 2026
    918258d
  18. added a commit that references this issue on Jul 22, 2026
    88cfd00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.D-papercutDiagnostics: An error or lint that needs small tweaks.E-help-wantedCall for participation: Help is requested to fix this issue.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