Skip to content

Improve consistency of attribute error messages#159755

Merged
rust-bors[bot] merged 5 commits into
rust-lang:mainfrom
nnethercote:attribute-error-messages
Jul 24, 2026
Merged

Improve consistency of attribute error messages#159755
rust-bors[bot] merged 5 commits into
rust-lang:mainfrom
nnethercote:attribute-error-messages

Conversation

@nnethercote

Copy link
Copy Markdown
Contributor

This PR aims to improve how attributes are referred to in error messages. A lot of test outputs will change, so there will be follow-ups, but this PR has enough changes to cover a lot of cases and give a good feel for where things are headed.

r? @estebank

@rustbot

rustbot commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred to diagnostic attributes.

cc @mejrs

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Jul 23, 2026
@nnethercote

Copy link
Copy Markdown
Contributor Author

Some more details: there is tremendous inconsistency in how attributes are referred to in error messages. In error lines, we see all of these (and possibly more) in different messages:

  • the #[foo] attribute is...
  • the foo attribute is...
  • attribute foo is...
  • foo is...
  • foo is...

Furthermore, carets sometimes point at the full attribute (including the #[/#![/] delimiters), sometimes at just the "inner" (everything within the delimiters), and sometimes at something more specific such as the attribute path. Examples:

// The full attribute including delimiters.
error[E0658]: the `#[coroutine]` attribute is an experimental feature
   |
LL |     let _ = #[coroutine] || yield true;
   |             ^^^^^^^^^^^^

// Just the attribute path.
error: cannot find attribute `lint` in this scope
   |
LL | #[lint("this is an example message", code = E0123)]
   |   ^^^^

Often the error line says something that doesn't match the actual source code pointed to by the carets. Examples:

// Error line omits attribute arguments.
error: the `#![crate_name]` attribute can only be used at the crate root
   |
LL | #![crate_name = "bar"]
   | ^^^^^^^^^^^^^^^^^^^^^^

// Error line omits the `unsafe(..)`.
error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
   |
LL | #[unsafe(proc_macro)]                             
   | ^^^^^^^^^^^^^^^^^^^^^  

// Error line omits the `cfg_attr(broken, ..)`.
error[E0658]: the `#[no_core]` attribute is an experimental feature
   |
LL | #![cfg_attr(broken, no_core)]                     
   |                     ^^^^^^^  

// Error line omits the `!`.
error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature
   |
LL | #![needs_panic_runtime]
   | ^^^^^^^^^^^^^^^^^^^^^^^

I propose the following:

  • As much as possible, use only the backticked attribute path in error lines.
    • The form "the foo attribute" should be used whenever it makes sense.
    • Some exceptions, e.g. "cannot find attribute foo in this scope" because that message is used for things other than attributes.
    • This avoids writing text that doesn't appear in the code, e.g. avoids inconsistencies with omitted arguments and unsafe and cfg_attr.
  • As much as possible, highlight just the attribute path with carets.
    • This is the most specific highlighting, and matches with what's named in the error line.
    • But when the error is in arguments to an attribute, the carets will still include the arguments.

This covers the vast majority of cases. There will be some exceptions, e.g. when suggesting what to write:

= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum

or when the delimiters are significant:

error: an inner attribute is not permitted in this context
   | 
LL |     let a = #![allow(warnings)] (1, 2);
   |             ^^^^^^^^^^^^^^^^^^^
   |                                                                    
   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files                
   = note: outer attributes, like `#[test]`, annotate the item following them

These cases are rare.

cc @petrochenkov

@rust-log-analyzer

This comment has been minimized.

@nnethercote
nnethercote force-pushed the attribute-error-messages branch from aaef4d8 to d8b48a3 Compare July 23, 2026 05:00
@nnethercote

Copy link
Copy Markdown
Contributor Author

The form "the foo attribute" should be used whenever it makes sense.

In case it's relevant: the Rust reference mostly uses this form, e.g. "the test attribute", "the derive attribute". (Although it also sometimes uses e.g. "the #[expect(C)] attribute", "the #[diagnostic] attribute".)

@rust-log-analyzer

This comment has been minimized.

@nnethercote
nnethercote force-pushed the attribute-error-messages branch from d8b48a3 to 1eb0ce9 Compare July 23, 2026 07:52
@rust-log-analyzer

This comment has been minimized.

@mejrs mejrs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been mildly annoyed by these inconsistencies before, this is much better 👍

Can you also add this to the diagnostic style guide? https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-output-style-guide

View changes since this review

@nnethercote
nnethercote force-pushed the attribute-error-messages branch from 1eb0ce9 to 41a538b Compare July 23, 2026 12:07
@nnethercote

Copy link
Copy Markdown
Contributor Author

Can you also add this to the diagnostic style guide?

Happy to, if/when this gets approval from reviewers :)

@rust-log-analyzer

This comment has been minimized.

@estebank estebank left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me after fixing CI

View changes since this review

// If the span is the full attribute (including the `#[`/`]` delimiters) shrink it to
// exclude those delimiters, because that's what we want in error messages.
if span == self.attr_span {
span = self.inner_span;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hacky, but ok.

@nnethercote
nnethercote force-pushed the attribute-error-messages branch from 41a538b to f5283e1 Compare July 23, 2026 22:44
@rustbot

rustbot commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

rustc-dev-guide is developed in its own repository. If possible, consider making this change to rust-lang/rustc-dev-guide instead.

cc @BoxyUwU, @tshepang

@rustbot rustbot added the A-rustc-dev-guide Area: rustc-dev-guide label Jul 23, 2026
@nnethercote

Copy link
Copy Markdown
Contributor Author

I added an extra commit with a style guide addition.

@rust-log-analyzer

This comment has been minimized.

These changes involve the error messages produced in
`check_attribute_stability`, plus some related ones.

The basic idea:
- Use "the `foo` attribute" in `error` lines as much as possible, where
  `foo` is the attribute's path.
- Point carets at just the attribute's path, to match the `error` line.
Mostly in a fashion similar to the previous commit.

There is one exceptional case: for errors involving `repr` the argument
is significant. For these, the argument is included in the error line
and the caret highlighting, e.g.
```
error: the `repr(C)` attribute cannot be used on functions
  --> $DIR/naked-with-invalid-repr-attr.rs:10:3
   |
LL | #[repr(C)]
   |   ^^^^^^^
   |
   = help: the `repr(C)` attribute can only be applied to data types
```

Contrast this with a more typical argument-excluding case used
everywhere else:
```
error: the `rustc_abi` attribute cannot be used on associated consts
  --> $DIR/debug.rs:46:7
   |
LL |     #[rustc_abi(debug)]
   |       ^^^^^^^^^
   |
   = help: the `rustc_abi` attribute can be applied to functions and type aliases
```
@nnethercote
nnethercote force-pushed the attribute-error-messages branch from 37ed28c to cd8a779 Compare July 24, 2026 03:04
@nnethercote

Copy link
Copy Markdown
Contributor Author

@bors r=estebank

@rust-bors

rust-bors Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

📌 Commit cd8a779 has been approved by estebank

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 24, 2026
rust-bors Bot pushed a commit that referenced this pull request Jul 24, 2026
Rollup of 14 pull requests

Successful merges:

 - #159765 (Avoid spurious rebuilds of JSON docs in bootstrap)
 - #159781 (Update bootstrap to use -Zembed-metadata=no instead of -Zno-embed-metadata)
 - #158362 (trait solver: account for universes from replace_bound_vars)
 - #158372 (rustfmt: Discover modules via `cfg_select!`)
 - #159173 (Add allowed list check on EII implementations attributes)
 - #159718 (Make `DocLinkResMap` an `FxIndexMap`)
 - #159722 ( [rustdoc] Retrieve `cfg_attr` information for derived impls for `doc_cfg` feature)
 - #159731 (std: Implement futex on wasip3 targets, update target spec)
 - #159755 (Improve consistency of attribute error messages)
 - #155795 (constify `vec![1, 2, 3]` macro)
 - #157776 (ci: Enable autodiff tests on x86_64 linux)
 - #158766 (Promote riscv64-unknown-linux-musl to tier 2 with host tools)
 - #159271 (str: add ASCII fast path to word_to_titlecase)
 - #159667 (Make some parser structured suggestions verbose and tweak their wording)
@rust-bors
rust-bors Bot merged commit 59906a3 into rust-lang:main Jul 24, 2026
13 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Jul 24, 2026
rust-timer added a commit that referenced this pull request Jul 24, 2026
Rollup merge of #159755 - nnethercote:attribute-error-messages, r=estebank

Improve consistency of attribute error messages

This PR aims to improve how attributes are referred to in error messages. A lot of test outputs will change, so there will be follow-ups, but this PR has enough changes to cover a lot of cases and give a good feel for where things are headed.

r? @estebank
github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Jul 25, 2026
Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#159765 (Avoid spurious rebuilds of JSON docs in bootstrap)
 - rust-lang/rust#159781 (Update bootstrap to use -Zembed-metadata=no instead of -Zno-embed-metadata)
 - rust-lang/rust#158362 (trait solver: account for universes from replace_bound_vars)
 - rust-lang/rust#158372 (rustfmt: Discover modules via `cfg_select!`)
 - rust-lang/rust#159173 (Add allowed list check on EII implementations attributes)
 - rust-lang/rust#159718 (Make `DocLinkResMap` an `FxIndexMap`)
 - rust-lang/rust#159722 ( [rustdoc] Retrieve `cfg_attr` information for derived impls for `doc_cfg` feature)
 - rust-lang/rust#159731 (std: Implement futex on wasip3 targets, update target spec)
 - rust-lang/rust#159755 (Improve consistency of attribute error messages)
 - rust-lang/rust#155795 (constify `vec![1, 2, 3]` macro)
 - rust-lang/rust#157776 (ci: Enable autodiff tests on x86_64 linux)
 - rust-lang/rust#158766 (Promote riscv64-unknown-linux-musl to tier 2 with host tools)
 - rust-lang/rust#159271 (str: add ASCII fast path to word_to_titlecase)
 - rust-lang/rust#159667 (Make some parser structured suggestions verbose and tweak their wording)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-rustc-dev-guide Area: rustc-dev-guide S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants