Rollup merge of #138336 - jyn514:crate-attr-diagnostics, r=compiler-errors

Improve `-Z crate-attr` diagnostics

- Show the `#![ ... ]` in the span (to make it clear that it should not
  be included in the CLI argument)
- Show more detailed errors when the crate has valid token trees but
  invalid syntax.
  Previously, `crate-attr=feature(foo),feature(bar)` would just say
  "invalid crate attribute" and point at the comma. Now, it explicitly
  says that the comma was unexpected, which is useful when using
  `--error-format=short`. It also fixes the column to show the correct
  span.
- Recover from parse errors. Previously we would abort immediately on
  syntax errors; now we go on to try and type-check the rest of the
  crate.

The new diagnostic code also happens to be slightly shorter.

r? diagnostics
This commit is contained in:
Jacob Pratt 2025-04-13 23:57:37 -04:00 committed by GitHub
commit 2b6835bf54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 82 additions and 78 deletions

View file

@ -627,7 +627,7 @@ pub fn mk_doc_comment(
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
}
pub fn mk_attr(
fn mk_attr(
g: &AttrIdGenerator,
style: AttrStyle,
unsafety: Safety,

View file

@ -231,8 +231,6 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
builtin_macros_format_use_positional = consider using a positional formatting argument instead
builtin_macros_invalid_crate_attribute = invalid crate attribute
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
.note = only one `#[default]` attribute is needed
.label = `#[default]` used here

View file

@ -1,44 +1,37 @@
//! Attributes injected into the crate root from command line using `-Z crate-attr`.
use rustc_ast::attr::mk_attr;
use rustc_ast::{self as ast, AttrItem, AttrStyle, token};
use rustc_parse::parser::ForceCollect;
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_ast::{self as ast};
use rustc_errors::Diag;
use rustc_parse::parser::attr::InnerAttrPolicy;
use rustc_parse::{parse_in, source_str_to_stream};
use rustc_session::parse::ParseSess;
use rustc_span::FileName;
use crate::errors;
pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
for raw_attr in attrs {
let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
psess,
FileName::cli_crate_attr_source_code(raw_attr),
raw_attr.clone(),
));
let start_span = parser.token.span;
let AttrItem { unsafety, path, args, tokens: _ } =
match parser.parse_attr_item(ForceCollect::No) {
Ok(ai) => ai,
Err(err) => {
let source = format!("#![{raw_attr}]");
let parse = || -> Result<ast::Attribute, Vec<Diag<'_>>> {
let tokens = source_str_to_stream(
psess,
FileName::cli_crate_attr_source_code(raw_attr),
source,
None,
)?;
parse_in(psess, tokens, "<crate attribute>", |p| {
p.parse_attribute(InnerAttrPolicy::Permitted)
})
.map_err(|e| vec![e])
};
let meta = match parse() {
Ok(meta) => meta,
Err(errs) => {
for err in errs {
err.emit();
continue;
}
};
let end_span = parser.token.span;
if parser.token != token::Eof {
psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
continue;
}
continue;
}
};
krate.attrs.push(mk_attr(
&psess.attr_id_generator,
AttrStyle::Inner,
unsafety,
path,
args,
start_span.to(end_span),
));
krate.attrs.push(meta);
}
}

View file

@ -109,13 +109,6 @@ pub(crate) struct ProcMacro {
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_invalid_crate_attribute)]
pub(crate) struct InvalidCrateAttr {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_non_abi)]
pub(crate) struct NonABI {

View file

@ -1,20 +1,20 @@
error: unknown start of token: `
--> <crate attribute>:1:1
--> <crate attribute>:1:4
|
LL | `%~@$#
| ^
LL | #![`%~@$#]
| ^
|
help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
|
LL - `%~@$#
LL + '%~@$#
LL - #![`%~@$#]
LL + #!['%~@$#]
|
error: expected identifier, found `%`
--> <crate attribute>:1:2
--> <crate attribute>:1:5
|
LL | `%~@$#
| ^ expected identifier
LL | #![`%~@$#]
| ^ expected identifier
error: aborting due to 2 previous errors

View file

@ -1,5 +1,3 @@
//@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline'
fn foo() {}
//~? ERROR unexpected closing delimiter: `]`
//~? ERROR unexpected token
fn foo() {} //~ ERROR `main` function not found

View file

@ -1,8 +1,15 @@
error: unexpected closing delimiter: `]`
--> <crate attribute>:1:19
error: unexpected token: keyword `fn`
--> <crate attribute>:1:23
|
LL | feature(yeet_expr)]fn main(){}#[inline
| ^ unexpected closing delimiter
LL | #![feature(yeet_expr)]fn main(){}#[inline]
| ^^ unexpected token after this
error: aborting due to 1 previous error
error[E0601]: `main` function not found in crate `injection`
--> $DIR/injection.rs:3:12
|
LL | fn foo() {}
| ^ consider adding a `main` function to `$DIR/injection.rs`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0601`.

View file

@ -0,0 +1,3 @@
//@ compile-flags: -Zcrate-attr=feature(yeet_expr)]#![allow(warnings)
//~? ERROR unexpected token
fn foo() {} //~ ERROR `main` function not found

View file

@ -0,0 +1,15 @@
error: unexpected token: `#`
--> <crate attribute>:1:23
|
LL | #![feature(yeet_expr)]#![allow(warnings)]
| ^ unexpected token after this
error[E0601]: `main` function not found in crate `injection2`
--> $DIR/injection2.rs:3:12
|
LL | fn foo() {}
| ^ consider adding a `main` function to `$DIR/injection2.rs`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0601`.

View file

@ -1,8 +1,8 @@
error: expected identifier, found `#`
--> <crate attribute>:1:1
--> <crate attribute>:1:4
|
LL | #![feature(foo)]
| ^ expected identifier
LL | #![#![feature(foo)]]
| ^ expected identifier
error: aborting due to 1 previous error

View file

@ -1,5 +1,3 @@
//@ compile-flags: -Zcrate-attr=feature(foo),feature(bar)
//~? ERROR expected `]`
fn main() {}
//~? ERROR invalid crate attribute

View file

@ -1,8 +1,8 @@
error: invalid crate attribute
--> <crate attribute>:1:1
error: expected `]`, found `,`
--> <crate attribute>:1:16
|
LL | feature(foo),feature(bar)
| ^^^^^^^^^^^^^
LL | #![feature(foo),feature(bar)]
| ^ expected `]`
error: aborting due to 1 previous error

View file

@ -1,6 +1,4 @@
// Show diagnostics for unbalanced parens.
//@ compile-flags: -Zcrate-attr=(
//~? ERROR mismatched closing delimiter
fn main() {}
//~? ERROR this file contains an unclosed delimiter

View file

@ -1,10 +1,11 @@
error: this file contains an unclosed delimiter
--> <crate attribute>:1:2
error: mismatched closing delimiter: `]`
--> <crate attribute>:1:4
|
LL | (
| -^
| |
| unclosed delimiter
LL | #![(]
| -^^ mismatched closing delimiter
| ||
| |unclosed delimiter
| closing delimiter possibly meant for this
error: aborting due to 1 previous error