From 747b7b39e21e45743b69e3370d8c083833579ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 22 Feb 2025 03:48:48 +0000 Subject: [PATCH] Fix incorrect `cfg` structured suggestion Keep a span for the attribute *within* the square brackets as part of the `AttrKind`. ``` error: `cfg` is not followed by parentheses --> $DIR/cfg-attr-syntax-validation.rs:4:1 | LL | #[cfg = 10] | ^^^^^^^^^^^ | help: expected syntax is | LL - #[cfg = 10] LL + #[cfg(/* predicate */)] | ``` Noticed in https://github.com/rust-lang/rust/pull/137343#discussion_r1964310938. --- compiler/rustc_ast/src/ast.rs | 2 + compiler/rustc_ast/src/attr/mod.rs | 26 ++++++--- compiler/rustc_ast/src/mut_visit.rs | 6 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 2 + .../src/alloc_error_handler.rs | 2 +- .../src/assert/context.rs | 7 ++- .../rustc_builtin_macros/src/cmdline_attrs.rs | 9 ++- .../src/deriving/clone.rs | 2 +- .../src/deriving/cmp/eq.rs | 6 +- .../src/deriving/cmp/ord.rs | 2 +- .../src/deriving/cmp/partial_eq.rs | 2 +- .../src/deriving/cmp/partial_ord.rs | 2 +- .../src/deriving/coerce_pointee.rs | 2 +- .../src/deriving/debug.rs | 2 +- .../src/deriving/default.rs | 2 +- .../src/deriving/generic/mod.rs | 2 +- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../src/global_allocator.rs | 2 +- .../src/proc_macro_harness.rs | 6 +- .../src/standard_library_imports.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 10 ++-- .../rustc_builtin_macros/src/test_harness.rs | 7 ++- compiler/rustc_expand/src/build.rs | 22 +++++-- compiler/rustc_expand/src/config.rs | 19 ++++-- compiler/rustc_expand/src/errors.rs | 12 ++-- compiler/rustc_parse/src/parser/attr.rs | 6 +- src/librustdoc/clean/types.rs | 2 +- tests/rustdoc-ui/doc-cfg.stderr | 14 ++++- tests/rustdoc-ui/invalid-cfg.stderr | 8 ++- .../cfg-attr-syntax-validation.rs | 5 ++ .../cfg-attr-syntax-validation.stderr | 58 +++++++++++++++++-- tests/ui/imports/unused-macro-use.stderr | 4 +- tests/ui/macros/macro-shadowing.stderr | 4 +- .../proc-macro/proc-macro-attributes.stderr | 16 ++--- .../rust-2018/macro-use-warned-against.stderr | 8 +-- 37 files changed, 205 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 29c1d34a125a4..9294eee6a3a61 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3034,6 +3034,7 @@ impl NormalAttr { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None, + span: ident.span, }, tokens: None, } @@ -3047,6 +3048,7 @@ pub struct AttrItem { pub args: AttrArgs, // Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`. pub tokens: Option, + pub span: Span, } impl AttrItem { diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index df2f4b8871249..d4dfa1c7f639c 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -219,7 +219,7 @@ impl Attribute { /// Extracts the MetaItem from inside this Attribute. pub fn meta(&self) -> Option { match &self.kind { - AttrKind::Normal(normal) => normal.item.meta(self.span), + AttrKind::Normal(normal) => normal.item.meta(), AttrKind::DocComment(..) => None, } } @@ -285,12 +285,12 @@ impl AttrItem { } } - pub fn meta(&self, span: Span) -> Option { + pub fn meta(&self) -> Option { Some(MetaItem { unsafety: Safety::Default, path: self.path.clone(), kind: self.meta_kind()?, - span, + span: self.span(), }) } @@ -406,7 +406,7 @@ impl MetaItem { Path { span, segments, tokens: None } } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt { - token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), + token::Nonterminal::NtMeta(item) => return item.meta(), token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, }, @@ -620,8 +620,15 @@ pub fn mk_attr( path: Path, args: AttrArgs, span: Span, + inner_span: Span, ) -> Attribute { - mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span) + mk_attr_from_item( + g, + AttrItem { unsafety, path, args, tokens: None, span: inner_span }, + None, + style, + span, + ) } pub fn mk_attr_from_item( @@ -645,10 +652,11 @@ pub fn mk_attr_word( unsafety: Safety, name: Symbol, span: Span, + inner_span: Span, ) -> Attribute { let path = Path::from_ident(Ident::new(name, span)); let args = AttrArgs::Empty; - mk_attr(g, style, unsafety, path, args, span) + mk_attr(g, style, unsafety, path, args, span, inner_span) } pub fn mk_attr_nested_word( @@ -658,6 +666,7 @@ pub fn mk_attr_nested_word( outer: Symbol, inner: Symbol, span: Span, + inner_span: Span, ) -> Attribute { let inner_tokens = TokenStream::new(vec![TokenTree::Token( Token::from_ast_ident(Ident::new(inner, span)), @@ -670,7 +679,7 @@ pub fn mk_attr_nested_word( delim: Delimiter::Parenthesis, tokens: inner_tokens, }); - mk_attr(g, style, unsafety, path, attr_args, span) + mk_attr(g, style, unsafety, path, attr_args, span, inner_span) } pub fn mk_attr_name_value_str( @@ -680,6 +689,7 @@ pub fn mk_attr_name_value_str( name: Symbol, val: Symbol, span: Span, + inner_span: Span, ) -> Attribute { let lit = token::Lit::new(token::Str, escape_string_symbol(val), None); let expr = P(Expr { @@ -691,7 +701,7 @@ pub fn mk_attr_name_value_str( }); let path = Path::from_ident(Ident::new(name, span)); let args = AttrArgs::Eq { eq_span: span, expr }; - mk_attr(g, style, unsafety, path, args, span) + mk_attr(g, style, unsafety, path, args, span, inner_span) } pub fn filter_by_name(attrs: &[A], name: Symbol) -> impl Iterator { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 40b29fdba2506..221cf280e8bb4 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -723,13 +723,14 @@ fn walk_attribute(vis: &mut T, attr: &mut Attribute) { match kind { AttrKind::Normal(normal) => { let NormalAttr { - item: AttrItem { unsafety: _, path, args, tokens }, + item: AttrItem { unsafety: _, path, args, tokens, span }, tokens: attr_tokens, } = &mut **normal; vis.visit_path(path); visit_attr_args(vis, args); visit_lazy_tts(vis, tokens); visit_lazy_tts(vis, attr_tokens); + vis.visit_span(span); } AttrKind::DocComment(_kind, _sym) => {} } @@ -909,10 +910,11 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { token::NtExpr(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr), token::NtMeta(item) => { - let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut(); + let AttrItem { unsafety: _, path, args, tokens, span } = item.deref_mut(); vis.visit_path(path); visit_attr_args(vis, args); visit_lazy_tts(vis, tokens); + vis.visit_span(span); } token::NtPath(path) => vis.visit_path(path), } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1cb32b56875c3..ea8a0ce8d5711 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1308,7 +1308,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) match kind { AttrKind::Normal(normal) => { let NormalAttr { item, tokens: _ } = &**normal; - let AttrItem { unsafety: _, path, args, tokens: _ } = item; + let AttrItem { unsafety: _, path, args, tokens: _, span: _ } = item; try_visit!(visitor.visit_path(path, DUMMY_NODE_ID)); try_visit!(walk_attr_args(visitor, args)); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index efbd1711daa92..94224cacbaabf 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1985,6 +1985,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sym::allow, sym::unreachable_code, try_span, + try_span, ); let attrs: AttrVec = thin_vec![attr]; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 44e956dc37f3e..22d063c25c069 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -257,6 +257,7 @@ pub fn print_crate<'a>( sym::feature, sym::prelude_import, DUMMY_SP, + DUMMY_SP, ); s.print_attribute(&fake_attr); @@ -270,6 +271,7 @@ pub fn print_crate<'a>( Safety::Default, sym::no_std, DUMMY_SP, + DUMMY_SP, ); s.print_attribute(&fake_attr); } diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 78bf2195975d5..ceb941f6afd8d 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -90,7 +90,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span body, })); - let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; + let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span, span)]; let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); cx.stmt_item(sig_span, item) diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index bb9dc651cec25..9192dca5339d7 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -113,7 +113,12 @@ impl<'cx, 'a> Context<'cx, 'a> { self.cx.item( self.span, Ident::empty(), - thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)], + thin_vec![self.cx.attr_nested_word( + sym::allow, + sym::unused_imports, + self.span, + self.span + )], ItemKind::Use(UseTree { prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), kind: UseTreeKind::Nested { diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index 6afd8c4b43b9a..8f057df7af33a 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -17,8 +17,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { raw_attr.clone(), )); - let start_span = parser.token.span; - let AttrItem { unsafety, path, args, tokens: _ } = + let AttrItem { unsafety, path, args, tokens: _, span } = match parser.parse_attr_item(ForceCollect::No) { Ok(ai) => ai, Err(err) => { @@ -26,9 +25,8 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { continue; } }; - let end_span = parser.token.span; if parser.token != token::Eof { - psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); + psess.dcx().emit_err(errors::InvalidCrateAttr { span }); continue; } @@ -38,7 +36,8 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { unsafety, path, args, - start_span.to(end_span), + span, + span, )); } } diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c3656e8244fe0..e078ceceffc0e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -81,7 +81,7 @@ pub(crate) fn expand_deriving_clone( explicit_self: true, nonself_args: Vec::new(), ret_ty: Self_, - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: substructure, }], diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index eca79e4dc4897..7041ba8d1c9c1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -32,9 +32,9 @@ pub(crate) fn expand_deriving_eq( nonself_args: vec![], ret_ty: Unit, attributes: thin_vec![ - cx.attr_word(sym::inline, span), - cx.attr_nested_word(sym::doc, sym::hidden, span), - cx.attr_nested_word(sym::coverage, sym::off, span) + cx.attr_word(sym::inline, span, span), + cx.attr_nested_word(sym::doc, sym::hidden, span, span), + cx.attr_nested_word(sym::coverage, sym::off, span, span) ], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 1ed44c20bc61e..ff93ed88a8b77 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -28,7 +28,7 @@ pub(crate) fn expand_deriving_ord( explicit_self: true, nonself_args: vec![(self_ref(), sym::other)], ret_ty: Path(path_std!(cmp::Ordering)), - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), }], diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 4b93b3414c76b..fed0f98cf986c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -95,7 +95,7 @@ pub(crate) fn expand_deriving_partial_eq( explicit_self: true, nonself_args: vec![(self_ref(), sym::other)], ret_ty: Path(path_local!(bool)), - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))), }]; diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 7958e037555d5..16a279a5a5914 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -47,7 +47,7 @@ pub(crate) fn expand_deriving_partial_ord( explicit_self: true, nonself_args: vec![(self_ref(), sym::other)], ret_ty, - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_partial_cmp(cx, span, substr, discr_then_data) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 5aed9f76f144f..a43cc0e9c1031 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -99,7 +99,7 @@ pub(crate) fn expand_deriving_coerce_pointee( // Declare helper function that adds implementation blocks. // FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls - let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),]; + let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span, span),]; // # Validity assertion which will be checked later in `rustc_hir_analysis::coherence::builtins`. { let trait_path = diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 8ab21986e68a0..48b314d1a1a5a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -32,7 +32,7 @@ pub(crate) fn expand_deriving_debug( explicit_self: true, nonself_args: vec![(fmtr, sym::f)], ret_ty: Path(path_std!(fmt::Result)), - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 1fe567e23f455..c3a1f31745463 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -35,7 +35,7 @@ pub(crate) fn expand_deriving_default( explicit_self: false, nonself_args: Vec::new(), ret_ty: Self_, - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| { match substr.fields { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 6b59ac2582755..3fd7c60aa22e4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -777,7 +777,7 @@ impl<'a> TraitDef<'a> { let path = cx.path_all(self.span, false, vec![type_ident], self_params); let self_type = cx.ty_path(path); - let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),]; + let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span, self.span)]; let opt_trait_ref = Some(trait_ref); cx.item( diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 6e6dbe19e4d1a..9db2c3ab1e918 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -33,7 +33,7 @@ pub(crate) fn expand_deriving_hash( explicit_self: true, nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], ret_ty: Unit, - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![cx.attr_word(sym::inline, span, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 8fdbbf8e704a9..e6c9c5a1a5664 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -105,7 +105,7 @@ impl AllocFnFactory<'_, '_> { } fn attrs(&self) -> AttrVec { - thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)] + thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span, self.span)] } fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec) -> P { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index ee6475c8b8e91..545e957275afc 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -369,9 +369,9 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { cx.expr_array_ref(span, decls), ) .map(|mut i| { - i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span)); - i.attrs.push(cx.attr_word(sym::used, span)); - i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span)); + i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span, span)); + i.attrs.push(cx.attr_word(sym::used, span, span)); + i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span, span)); i }); diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 6933ca09349a1..00cdae249409f 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -44,7 +44,7 @@ pub fn inject( let item = cx.item( span, Ident::new(name, ident_span), - thin_vec![cx.attr_word(sym::macro_use, span)], + thin_vec![cx.attr_word(sym::macro_use, span, span)], ast::ItemKind::ExternCrate(None), ); @@ -68,7 +68,7 @@ pub fn inject( let use_item = cx.item( span, Ident::empty(), - thin_vec![cx.attr_word(sym::prelude_import, span)], + thin_vec![cx.attr_word(sym::prelude_import, span, span)], ast::ItemKind::Use(ast::UseTree { prefix: cx.path(span, import_path), kind: ast::UseTreeKind::Glob, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index a05fff2dcd1c1..ec65dd3a5c16d 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -63,7 +63,7 @@ pub(crate) fn expand_test_case( tokens: None, }; item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); - item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); + item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp, sp)); item }); @@ -200,7 +200,7 @@ pub(crate) fn expand_test_or_bench( // corresponding macro declaration in `core::macros`. let coverage_off = |mut expr: P| { assert_matches!(expr.kind, ast::ExprKind::Closure(_)); - expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp)); + expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp, sp)); expr }; @@ -273,11 +273,11 @@ pub(crate) fn expand_test_or_bench( Ident::new(item.ident.name, sp), thin_vec![ // #[cfg(test)] - cx.attr_nested_word(sym::cfg, sym::test, attr_sp), + cx.attr_nested_word(sym::cfg, sym::test, attr_sp, attr_sp), // #[rustc_test_marker = "test_case_sort_key"] - cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), + cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp, attr_sp), // #[doc(hidden)] - cx.attr_nested_word(sym::doc, sym::hidden, attr_sp), + cx.attr_nested_word(sym::doc, sym::hidden, attr_sp, attr_sp), ], // const $ident: test::TestDescAndFn = ast::ItemKind::Const( diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 472e16e62d5b0..5f0f4af102172 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -216,6 +216,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { sym::allow, sym::dead_code, self.def_site, + self.def_site, ); item.attrs.retain(|attr| !attr.has_name(sym::rustc_main)); item.attrs.push(allow_dead_code); @@ -321,11 +322,11 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { ); // #[rustc_main] - let main_attr = ecx.attr_word(sym::rustc_main, sp); + let main_attr = ecx.attr_word(sym::rustc_main, sp, sp); // #[coverage(off)] - let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp); + let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp, sp); // #[doc(hidden)] - let doc_hidden_attr = ecx.attr_nested_word(sym::doc, sym::hidden, sp); + let doc_hidden_attr = ecx.attr_nested_word(sym::doc, sym::hidden, sp, sp); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new())); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ee7f68cc2f01c..276338c72513a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -730,15 +730,21 @@ impl<'a> ExtCtxt<'a> { } // Builds `#[name]`. - pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute { + pub fn attr_word(&self, name: Symbol, span: Span, inner_span: Span) -> ast::Attribute { let g = &self.sess.psess.attr_id_generator; - attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span) + attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span, inner_span) } // Builds `#[name = val]`. // // Note: `span` is used for both the identifier and the value. - pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { + pub fn attr_name_value_str( + &self, + name: Symbol, + val: Symbol, + span: Span, + inner_span: Span, + ) -> ast::Attribute { let g = &self.sess.psess.attr_id_generator; attr::mk_attr_name_value_str( g, @@ -747,11 +753,18 @@ impl<'a> ExtCtxt<'a> { name, val, span, + inner_span, ) } // Builds `#[outer(inner)]`. - pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute { + pub fn attr_nested_word( + &self, + outer: Symbol, + inner: Symbol, + span: Span, + inner_span: Span, + ) -> ast::Attribute { let g = &self.sess.psess.attr_id_generator; attr::mk_attr_nested_word( g, @@ -760,6 +773,7 @@ impl<'a> ExtCtxt<'a> { outer, inner, span, + inner_span, ) } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 83255b820178f..bd5d36f0c649a 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -6,7 +6,8 @@ use rustc_ast::tokenstream::{ AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree, }; use rustc_ast::{ - self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId, + self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, + NodeId, }; use rustc_attr_parsing as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; @@ -387,11 +388,15 @@ impl<'a> StripUnconfigured<'a> { return (true, None); } }; + let sugg_span = match &attr.kind { + AttrKind::Normal(attr) => attr.item.span, + _ => meta_item.span, + }; validate_attr::deny_builtin_meta_unsafety(&self.sess.psess, &meta_item); ( - parse_cfg(&meta_item, self.sess).is_none_or(|meta_item| { + parse_cfg(&meta_item, self.sess, sugg_span).is_none_or(|meta_item| { attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features) }), Some(meta_item), @@ -447,15 +452,19 @@ impl<'a> StripUnconfigured<'a> { } } -pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> { +pub fn parse_cfg<'a>( + meta_item: &'a MetaItem, + sess: &Session, + suggestion_span: Span, +) -> Option<&'a MetaItemInner> { let span = meta_item.span; match meta_item.meta_item_list() { None => { - sess.dcx().emit_err(InvalidCfg::NotFollowedByParens { span }); + sess.dcx().emit_err(InvalidCfg::NotFollowedByParens { span, suggestion_span }); None } Some([]) => { - sess.dcx().emit_err(InvalidCfg::NoPredicate { span }); + sess.dcx().emit_err(InvalidCfg::NoPredicate { span, suggestion_span }); None } Some([_, .., l]) => { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 89bdc7b6dfa5d..b6252e297d8ce 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -223,22 +223,26 @@ pub(crate) enum InvalidCfg { #[diag(expand_invalid_cfg_no_parens)] NotFollowedByParens { #[primary_span] + span: Span, #[suggestion( expand_invalid_cfg_expected_syntax, code = "cfg(/* predicate */)", - applicability = "has-placeholders" + applicability = "has-placeholders", + style = "verbose" )] - span: Span, + suggestion_span: Span, }, #[diag(expand_invalid_cfg_no_predicate)] NoPredicate { #[primary_span] + span: Span, #[suggestion( expand_invalid_cfg_expected_syntax, code = "cfg(/* predicate */)", - applicability = "has-placeholders" + applicability = "has-placeholders", + style = "verbose" )] - span: Span, + suggestion_span: Span, }, #[diag(expand_invalid_cfg_multiple_predicates)] MultiplePredicates { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 2691e6f56d68b..2237021740fde 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -273,6 +273,7 @@ impl<'a> Parser<'a> { // Attr items don't have attributes. self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| { + let lo = this.token.span; let is_unsafe = this.eat_keyword(exp!(Unsafe)); let unsafety = if is_unsafe { let unsafe_span = this.prev_token.span; @@ -287,8 +288,9 @@ impl<'a> Parser<'a> { if is_unsafe { this.expect(exp!(CloseParen))?; } + let span = lo.until(this.token.span); Ok(( - ast::AttrItem { unsafety, path, args, tokens: None }, + ast::AttrItem { unsafety, path, args, tokens: None, span }, Trailing::No, UsePreAttrPos::No, )) @@ -401,7 +403,7 @@ impl<'a> Parser<'a> { if let token::Interpolated(nt) = &self.token.kind && let token::NtMeta(attr_item) = &**nt { - match attr_item.meta(attr_item.path.span) { + match attr_item.meta() { Some(meta) => { self.bump(); return Ok(meta); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 178b6a60b41f7..d0ebca09092c7 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1054,7 +1054,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator // #[doc(cfg(...))] if let Some(cfg_mi) = item .meta_item() - .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) + .and_then(|item| rustc_expand::config::parse_cfg(item, sess, item.span)) { match Cfg::parse(cfg_mi) { Ok(new_cfg) => cfg &= new_cfg, diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr index 14b7b17e04d3a..8b87cb55d4536 100644 --- a/tests/rustdoc-ui/doc-cfg.stderr +++ b/tests/rustdoc-ui/doc-cfg.stderr @@ -2,7 +2,12 @@ error: `cfg` predicate is not specified --> $DIR/doc-cfg.rs:3:7 | LL | #[doc(cfg(), cfg(foo, bar))] - | ^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^ + | +help: expected syntax is + | +LL | #[doc(cfg(/* predicate */), cfg(foo, bar))] + | +++++++++++++++ error: multiple `cfg` predicates are specified --> $DIR/doc-cfg.rs:3:23 @@ -14,7 +19,12 @@ error: `cfg` predicate is not specified --> $DIR/doc-cfg.rs:7:7 | LL | #[doc(cfg())] - | ^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^ + | +help: expected syntax is + | +LL | #[doc(cfg(/* predicate */))] + | +++++++++++++++ error: multiple `cfg` predicates are specified --> $DIR/doc-cfg.rs:8:16 diff --git a/tests/rustdoc-ui/invalid-cfg.stderr b/tests/rustdoc-ui/invalid-cfg.stderr index dae238b052b8a..b6ccfa91ee249 100644 --- a/tests/rustdoc-ui/invalid-cfg.stderr +++ b/tests/rustdoc-ui/invalid-cfg.stderr @@ -2,7 +2,13 @@ error: `cfg` is not followed by parentheses --> $DIR/invalid-cfg.rs:2:7 | LL | #[doc(cfg = "x")] - | ^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^^^^^ + | +help: expected syntax is + | +LL - #[doc(cfg = "x")] +LL + #[doc(cfg(/* predicate */))] + | error: multiple `cfg` predicates are specified --> $DIR/invalid-cfg.rs:3:14 diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index d885281249203..b07eac80b179d 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -36,4 +36,9 @@ macro_rules! generate_s10 { generate_s10!(concat!("nonexistent")); +mod m { + #![cfg] //~ ERROR `cfg` is not followed by parentheses + #![cfg = 10] //~ ERROR `cfg` is not followed by parentheses + #![cfg()] //~ ERROR `cfg` predicate is not specified +} fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 3dd0823389cde..0b8369d351817 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -2,19 +2,35 @@ error: `cfg` is not followed by parentheses --> $DIR/cfg-attr-syntax-validation.rs:1:1 | LL | #[cfg] - | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^^ + | +help: expected syntax is + | +LL | #[cfg(/* predicate */)] + | +++++++++++++++++ error: `cfg` is not followed by parentheses --> $DIR/cfg-attr-syntax-validation.rs:4:1 | LL | #[cfg = 10] - | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^^^^^^^ + | +help: expected syntax is + | +LL - #[cfg = 10] +LL + #[cfg(/* predicate */)] + | error: `cfg` predicate is not specified --> $DIR/cfg-attr-syntax-validation.rs:7:1 | LL | #[cfg()] - | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + | ^^^^^^^^ + | +help: expected syntax is + | +LL | #[cfg(/* predicate */)] + | +++++++++++++++ error: multiple `cfg` predicates are specified --> $DIR/cfg-attr-syntax-validation.rs:10:10 @@ -54,6 +70,40 @@ LL | #[cfg(a = b"hi")] | | | help: consider removing the prefix +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:40:5 + | +LL | #![cfg] + | ^^^^^^^ + | +help: expected syntax is + | +LL | #![cfg(/* predicate */)] + | +++++++++++++++++ + +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:41:5 + | +LL | #![cfg = 10] + | ^^^^^^^^^^^^ + | +help: expected syntax is + | +LL - #![cfg = 10] +LL + #![cfg(/* predicate */)] + | + +error: `cfg` predicate is not specified + --> $DIR/cfg-attr-syntax-validation.rs:42:5 + | +LL | #![cfg()] + | ^^^^^^^^^ + | +help: expected syntax is + | +LL | #![cfg(/* predicate */)] + | +++++++++++++++ + error: expected unsuffixed literal, found `concat!("nonexistent")` --> $DIR/cfg-attr-syntax-validation.rs:30:25 | @@ -77,7 +127,7 @@ LL | generate_s10!(concat!("nonexistent")); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 11 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0537, E0565. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/imports/unused-macro-use.stderr b/tests/ui/imports/unused-macro-use.stderr index 7137a90e45956..fc5d5045fd6c3 100644 --- a/tests/ui/imports/unused-macro-use.stderr +++ b/tests/ui/imports/unused-macro-use.stderr @@ -1,8 +1,8 @@ error: unused `#[macro_use]` import - --> $DIR/unused-macro-use.rs:3:1 + --> $DIR/unused-macro-use.rs:3:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-use.rs:1:9 diff --git a/tests/ui/macros/macro-shadowing.stderr b/tests/ui/macros/macro-shadowing.stderr index a052b43ac10e4..77cc1afaf649f 100644 --- a/tests/ui/macros/macro-shadowing.stderr +++ b/tests/ui/macros/macro-shadowing.stderr @@ -1,8 +1,8 @@ error: `macro_two` is already in scope - --> $DIR/macro-shadowing.rs:12:5 + --> $DIR/macro-shadowing.rs:12:7 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ ... LL | m1!(); | ----- in this macro invocation diff --git a/tests/ui/proc-macro/proc-macro-attributes.stderr b/tests/ui/proc-macro/proc-macro-attributes.stderr index 140d879069040..3b681e1aeffa4 100644 --- a/tests/ui/proc-macro/proc-macro-attributes.stderr +++ b/tests/ui/proc-macro/proc-macro-attributes.stderr @@ -17,10 +17,10 @@ note: `B` could refer to the derive helper attribute defined here LL | #[derive(B)] | ^ note: `B` could also refer to the derive macro imported here - --> $DIR/proc-macro-attributes.rs:3:1 + --> $DIR/proc-macro-attributes.rs:3:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:10:3 @@ -35,10 +35,10 @@ note: `B` could refer to the derive helper attribute defined here LL | #[derive(B)] | ^ note: `B` could also refer to the derive macro imported here - --> $DIR/proc-macro-attributes.rs:3:1 + --> $DIR/proc-macro-attributes.rs:3:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:13:3 @@ -53,10 +53,10 @@ note: `B` could refer to the derive helper attribute defined here LL | #[derive(B)] | ^ note: `B` could also refer to the derive macro imported here - --> $DIR/proc-macro-attributes.rs:3:1 + --> $DIR/proc-macro-attributes.rs:3:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:16:3 @@ -71,10 +71,10 @@ note: `B` could refer to the derive helper attribute defined here LL | #[derive(B)] | ^ note: `B` could also refer to the derive macro imported here - --> $DIR/proc-macro-attributes.rs:3:1 + --> $DIR/proc-macro-attributes.rs:3:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ warning: derive helper attribute is used before it is introduced --> $DIR/proc-macro-attributes.rs:6:3 diff --git a/tests/ui/rust-2018/macro-use-warned-against.stderr b/tests/ui/rust-2018/macro-use-warned-against.stderr index 3ac1f12705170..c47827ab367e5 100644 --- a/tests/ui/rust-2018/macro-use-warned-against.stderr +++ b/tests/ui/rust-2018/macro-use-warned-against.stderr @@ -1,8 +1,8 @@ warning: applying the `#[macro_use]` attribute to an `extern crate` item is deprecated - --> $DIR/macro-use-warned-against.rs:7:1 + --> $DIR/macro-use-warned-against.rs:7:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: remove it and import macros at use sites with a `use` item instead note: the lint level is defined here @@ -12,10 +12,10 @@ LL | #![warn(macro_use_extern_crate, unused)] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused `#[macro_use]` import - --> $DIR/macro-use-warned-against.rs:9:1 + --> $DIR/macro-use-warned-against.rs:9:3 | LL | #[macro_use] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | note: the lint level is defined here --> $DIR/macro-use-warned-against.rs:5:33