From 0195758c1a6dfbbec0cf66e6a3009f6600328398 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 29 May 2024 23:36:11 +0300 Subject: [PATCH 1/2] ast: Standardize visiting order for attributes and node IDs --- compiler/rustc_ast/src/mut_visit.rs | 42 +++++++------- compiler/rustc_ast/src/visit.rs | 18 +++--- .../tests/ui/cfg_attr_cargo_clippy.stderr | 18 +++--- .../tests/ui/tabs_in_doc_comments.stderr | 48 ++++++++-------- .../tests/ui/unnecessary_clippy_cfg.stderr | 56 +++++++++---------- .../attributes/key-value-expansion-scope.rs | 8 +-- .../key-value-expansion-scope.stderr | 34 ++++++++++- .../feature-gate-optimize_attribute.stderr | 28 +++++----- .../feature-gate-staged_api.stderr | 12 ++-- ...issue-43106-gating-of-builtin-attrs.stderr | 15 ++++- .../issue-43106-gating-of-stable.stderr | 24 ++++---- .../issue-43106-gating-of-unstable.stderr | 24 ++++---- .../proc-macro/ambiguous-builtin-attrs.stderr | 30 +++++----- .../stability-attribute/issue-106589.stderr | 8 +-- 14 files changed, 205 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c9d2f5c779bb6..ed8bf58eb23ef 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -429,10 +429,10 @@ pub fn noop_flat_map_pat_field( ) -> SmallVec<[PatField; 1]> { let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp; vis.visit_id(id); + visit_attrs(attrs, vis); vis.visit_ident(ident); vis.visit_pat(pat); vis.visit_span(span); - visit_attrs(attrs, vis); smallvec![fp] } @@ -443,8 +443,8 @@ fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), UseTreeKind::Nested { items, .. } => { for (tree, id) in items { - vis.visit_use_tree(tree); vis.visit_id(id); + vis.visit_use_tree(tree); } } UseTreeKind::Glob => {} @@ -454,8 +454,8 @@ fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; - visit_attrs(attrs, vis); vis.visit_id(id); + visit_attrs(attrs, vis); vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); visit_opt(body, |body| vis.visit_expr(body)); @@ -548,10 +548,10 @@ pub fn noop_flat_map_variant( visitor: &mut T, ) -> SmallVec<[Variant; 1]> { let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; + visitor.visit_id(id); + visit_attrs(attrs, visitor); visitor.visit_ident(ident); visitor.visit_vis(vis); - visit_attrs(attrs, visitor); - visitor.visit_id(id); visitor.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); visitor.visit_span(span); @@ -565,8 +565,8 @@ fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mu fn noop_visit_path(Path { segments, span, tokens }: &mut Path, vis: &mut T) { vis.visit_span(span); for PathSegment { ident, id, args } in segments { - vis.visit_ident(ident); vis.visit_id(id); + vis.visit_ident(ident); visit_opt(args, |args| vis.visit_generic_args(args)); } visit_lazy_tts(tokens, vis); @@ -620,6 +620,7 @@ fn noop_visit_parenthesized_parameter_data( fn noop_visit_local(local: &mut P, vis: &mut T) { let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); vis.visit_id(id); + visit_attrs(attrs, vis); vis.visit_pat(pat); visit_opt(ty, |ty| vis.visit_ty(ty)); match kind { @@ -634,7 +635,6 @@ fn noop_visit_local(local: &mut P, vis: &mut T) { } vis.visit_span(span); visit_opt(colon_sp, |sp| vis.visit_span(sp)); - visit_attrs(attrs, vis); visit_lazy_tts(tokens, vis); } @@ -894,9 +894,9 @@ fn noop_visit_coroutine_kind(coroutine_kind: &mut CoroutineKind, CoroutineKind::Async { span, closure_id, return_impl_trait_id } | CoroutineKind::Gen { span, closure_id, return_impl_trait_id } | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => { - vis.visit_span(span); vis.visit_id(closure_id); vis.visit_id(return_impl_trait_id); + vis.visit_span(span); } } } @@ -932,8 +932,8 @@ fn noop_visit_precise_capturing_arg(arg: &mut PreciseCapturingArg vis.visit_lifetime(lt); } PreciseCapturingArg::Arg(path, id) => { - vis.visit_path(path); vis.visit_id(id); + vis.visit_path(path); } } } @@ -944,11 +944,11 @@ pub fn noop_flat_map_generic_param( ) -> SmallVec<[GenericParam; 1]> { let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param; vis.visit_id(id); + visit_attrs(attrs, vis); vis.visit_ident(ident); if let Some(colon_span) = colon_span { vis.visit_span(colon_span); } - visit_attrs(attrs, vis); visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); match kind { GenericParamKind::Lifetime => {} @@ -1015,16 +1015,16 @@ fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); } VariantData::Tuple(fields, id) => { - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); vis.visit_id(id); + fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); } VariantData::Unit(id) => vis.visit_id(id), } } fn noop_visit_trait_ref(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) { - vis.visit_path(path); vis.visit_id(ref_id); + vis.visit_path(path); } fn noop_visit_poly_trait_ref(p: &mut PolyTraitRef, vis: &mut T) { @@ -1039,12 +1039,12 @@ pub fn noop_flat_map_field_def( visitor: &mut T, ) -> SmallVec<[FieldDef; 1]> { let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd; + visitor.visit_id(id); + visit_attrs(attrs, visitor); visitor.visit_span(span); visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_vis(vis); - visitor.visit_id(id); visitor.visit_ty(ty); - visit_attrs(attrs, visitor); smallvec![fd] } @@ -1053,11 +1053,11 @@ pub fn noop_flat_map_expr_field( vis: &mut T, ) -> SmallVec<[ExprField; 1]> { let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f; + vis.visit_id(id); + visit_attrs(attrs, vis); vis.visit_ident(ident); vis.visit_expr(expr); - vis.visit_id(id); vis.visit_span(span); - visit_attrs(attrs, vis); smallvec![f] } @@ -1429,6 +1429,8 @@ pub fn noop_visit_expr( Expr { kind, id, span, attrs, tokens }: &mut Expr, vis: &mut T, ) { + vis.visit_id(id); + visit_attrs(attrs, vis); match kind { ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis), ExprKind::ConstBlock(anon_const) => { @@ -1449,8 +1451,8 @@ pub fn noop_visit_expr( args: call_args, span, }) => { - vis.visit_ident(ident); vis.visit_id(id); + vis.visit_ident(ident); visit_opt(seg_args, |args| vis.visit_generic_args(args)); vis.visit_method_receiver_expr(receiver); visit_thin_exprs(call_args, vis); @@ -1601,9 +1603,7 @@ pub fn noop_visit_expr( ExprKind::TryBlock(body) => vis.visit_block(body), ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {} } - vis.visit_id(id); vis.visit_span(span); - visit_attrs(attrs, vis); visit_lazy_tts(tokens, vis); } @@ -1645,8 +1645,8 @@ fn noop_flat_map_stmt_kind(kind: StmtKind, vis: &mut T) -> SmallV StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::MacCall(mut mac) => { let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut(); - vis.visit_mac_call(mac_); visit_attrs(attrs, vis); + vis.visit_mac_call(mac_); visit_lazy_tts(tokens, vis); smallvec![StmtKind::MacCall(mac)] } @@ -1657,8 +1657,8 @@ fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) { match &mut visibility.kind { VisibilityKind::Public | VisibilityKind::Inherited => {} VisibilityKind::Restricted { path, id, shorthand: _ } => { - vis.visit_path(path); vis.visit_id(id); + vis.visit_path(path); } } vis.visit_span(&mut visibility.span); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ce38a67ea69ab..e2ef0542bf9c1 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -298,8 +298,8 @@ pub trait Visitor<'ast>: Sized { } pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { - walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); + walk_list!(visitor, visit_item, &krate.items); V::Result::output() } @@ -462,25 +462,25 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) - where V: Visitor<'a>, { + walk_list!(visitor, visit_attribute, &variant.attrs); try_visit!(visitor.visit_ident(variant.ident)); try_visit!(visitor.visit_vis(&variant.vis)); try_visit!(visitor.visit_variant_data(&variant.data)); visit_opt!(visitor, visit_variant_discr, &variant.disr_expr); - walk_list!(visitor, visit_attribute, &variant.attrs); V::Result::output() } pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result { + walk_list!(visitor, visit_attribute, &f.attrs); try_visit!(visitor.visit_expr(&f.expr)); try_visit!(visitor.visit_ident(f.ident)); - walk_list!(visitor, visit_attribute, &f.attrs); V::Result::output() } pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result { + walk_list!(visitor, visit_attribute, &fp.attrs); try_visit!(visitor.visit_ident(fp.ident)); try_visit!(visitor.visit_pat(&fp.pat)); - walk_list!(visitor, visit_attribute, &fp.attrs); V::Result::output() } @@ -722,8 +722,8 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>( visitor: &mut V, param: &'a GenericParam, ) -> V::Result { - try_visit!(visitor.visit_ident(param.ident)); walk_list!(visitor, visit_attribute, ¶m.attrs); + try_visit!(visitor.visit_ident(param.ident)); walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound); match ¶m.kind { GenericParamKind::Lifetime => (), @@ -882,10 +882,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>( ctxt: AssocCtxt, ) -> V::Result { let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; + walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); try_visit!(visitor.visit_ident(ident)); try_visit!(kind.walk(item, ctxt, visitor)); - walk_list!(visitor, visit_attribute, attrs); V::Result::output() } @@ -898,10 +898,10 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>( } pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result { + walk_list!(visitor, visit_attribute, &field.attrs); try_visit!(visitor.visit_vis(&field.vis)); visit_opt!(visitor, visit_ident, field.ident); try_visit!(visitor.visit_ty(&field.ty)); - walk_list!(visitor, visit_attribute, &field.attrs); V::Result::output() } @@ -918,8 +918,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V: StmtKind::Empty => {} StmtKind::MacCall(mac) => { let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; - try_visit!(visitor.visit_mac_call(mac)); walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_mac_call(mac)); } } V::Result::output() @@ -1141,10 +1141,10 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::R } pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result { + walk_list!(visitor, visit_attribute, &arm.attrs); try_visit!(visitor.visit_pat(&arm.pat)); visit_opt!(visitor, visit_expr, &arm.guard); visit_opt!(visitor, visit_expr, &arm.body); - walk_list!(visitor, visit_attribute, &arm.attrs); V::Result::output() } diff --git a/src/tools/clippy/tests/ui/cfg_attr_cargo_clippy.stderr b/src/tools/clippy/tests/ui/cfg_attr_cargo_clippy.stderr index ddec0e648d10c..0a358f1a68475 100644 --- a/src/tools/clippy/tests/ui/cfg_attr_cargo_clippy.stderr +++ b/src/tools/clippy/tests/ui/cfg_attr_cargo_clippy.stderr @@ -1,12 +1,18 @@ error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:5:12 + --> tests/ui/cfg_attr_cargo_clippy.rs:3:13 | -LL | #[cfg_attr(feature = "cargo-clippy", derive(Debug))] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` +LL | #![cfg_attr(feature = "cargo-clippy", doc = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` | = note: `-D clippy::deprecated-clippy-cfg-attr` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::deprecated_clippy_cfg_attr)]` +error: `feature = "cargo-clippy"` was replaced by `clippy` + --> tests/ui/cfg_attr_cargo_clippy.rs:5:12 + | +LL | #[cfg_attr(feature = "cargo-clippy", derive(Debug))] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` + error: `feature = "cargo-clippy"` was replaced by `clippy` --> tests/ui/cfg_attr_cargo_clippy.rs:6:16 | @@ -37,11 +43,5 @@ error: `feature = "cargo-clippy"` was replaced by `clippy` LL | #[cfg(all(feature = "cargo-clippy"))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` -error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:3:13 - | -LL | #![cfg_attr(feature = "cargo-clippy", doc = "a")] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` - error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr index 23d5dcd3a8dab..aef6c39145263 100644 --- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr +++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr @@ -1,53 +1,53 @@ error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:10:9 + --> tests/ui/tabs_in_doc_comments.rs:6:5 | -LL | /// - First String: - | ^^^^ help: consider using four spaces per tab +LL | /// - first one + | ^^^^ help: consider using four spaces per tab | = note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]` error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:11:9 + --> tests/ui/tabs_in_doc_comments.rs:6:13 | -LL | /// - needs to be inside here - | ^^^^^^^^ help: consider using four spaces per tab +LL | /// - first one + | ^^^^^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:14:9 + --> tests/ui/tabs_in_doc_comments.rs:7:5 | -LL | /// - Second String: - | ^^^^ help: consider using four spaces per tab +LL | /// - second one + | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:15:9 + --> tests/ui/tabs_in_doc_comments.rs:7:14 | -LL | /// - needs to be inside here - | ^^^^^^^^ help: consider using four spaces per tab +LL | /// - second one + | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:5 + --> tests/ui/tabs_in_doc_comments.rs:10:9 | -LL | /// - first one - | ^^^^ help: consider using four spaces per tab +LL | /// - First String: + | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:13 + --> tests/ui/tabs_in_doc_comments.rs:11:9 | -LL | /// - first one - | ^^^^^^^^ help: consider using four spaces per tab +LL | /// - needs to be inside here + | ^^^^^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:7:5 + --> tests/ui/tabs_in_doc_comments.rs:14:9 | -LL | /// - second one - | ^^^^ help: consider using four spaces per tab +LL | /// - Second String: + | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:7:14 + --> tests/ui/tabs_in_doc_comments.rs:15:9 | -LL | /// - second one - | ^^^^ help: consider using four spaces per tab +LL | /// - needs to be inside here + | ^^^^^^^^ help: consider using four spaces per tab error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr index 16a8616529565..01f842a657de5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr @@ -1,61 +1,61 @@ error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:13:1 + --> tests/ui/unnecessary_clippy_cfg.rs:4:1 | -LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` +LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` | = note: `-D clippy::unnecessary-clippy-cfg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_clippy_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:15:36 + --> tests/ui/unnecessary_clippy_cfg.rs:6:37 | -LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: write instead: `#[deny(clippy::non_minimal_cfg)]` + = note: write instead: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:17:36 + --> tests/ui/unnecessary_clippy_cfg.rs:8:37 | -LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: write instead: `#[deny(clippy::non_minimal_cfg)]` + = note: write instead: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:19:1 + --> tests/ui/unnecessary_clippy_cfg.rs:10:1 | -LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` +LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:4:1 + --> tests/ui/unnecessary_clippy_cfg.rs:13:1 | -LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` +LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:6:37 + --> tests/ui/unnecessary_clippy_cfg.rs:15:36 | -LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: write instead: `#![deny(clippy::non_minimal_cfg)]` + = note: write instead: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:8:37 + --> tests/ui/unnecessary_clippy_cfg.rs:17:36 | -LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: write instead: `#![deny(clippy::non_minimal_cfg)]` + = note: write instead: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:10:1 + --> tests/ui/unnecessary_clippy_cfg.rs:19:1 | -LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` +LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` error: duplicated attribute --> tests/ui/unnecessary_clippy_cfg.rs:8:26 diff --git a/tests/ui/attributes/key-value-expansion-scope.rs b/tests/ui/attributes/key-value-expansion-scope.rs index b84fe4873c371..147e9bdbe241c 100644 --- a/tests/ui/attributes/key-value-expansion-scope.rs +++ b/tests/ui/attributes/key-value-expansion-scope.rs @@ -1,6 +1,6 @@ -#![doc = in_root!()] // FIXME, this is a bug +#![doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope -#![doc = in_mod_escape!()] // FIXME, this is a bug +#![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope #[doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope @@ -17,7 +17,7 @@ fn before() { macro_rules! in_root { () => { "" } } mod macros_stay { - #![doc = in_mod!()] // FIXME, this is a bug + #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope macro_rules! in_mod { () => { "" } } @@ -29,7 +29,7 @@ mod macros_stay { #[macro_use] mod macros_escape { - #![doc = in_mod_escape!()] // FIXME, this is a bug + #![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope macro_rules! in_mod_escape { () => { "" } } diff --git a/tests/ui/attributes/key-value-expansion-scope.stderr b/tests/ui/attributes/key-value-expansion-scope.stderr index a66ee9b17fb92..c7713a0ee09f2 100644 --- a/tests/ui/attributes/key-value-expansion-scope.stderr +++ b/tests/ui/attributes/key-value-expansion-scope.stderr @@ -1,3 +1,11 @@ +error: cannot find macro `in_root` in this scope + --> $DIR/key-value-expansion-scope.rs:1:10 + | +LL | #![doc = in_root!()] + | ^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + error: cannot find macro `in_mod` in this scope --> $DIR/key-value-expansion-scope.rs:2:10 | @@ -6,6 +14,14 @@ LL | #![doc = in_mod!()] | = help: have you added the `#[macro_use]` on the module/import? +error: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:3:10 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + error: cannot find macro `in_block` in this scope --> $DIR/key-value-expansion-scope.rs:4:10 | @@ -78,6 +94,22 @@ LL | #![doc = in_block!()] | = help: have you added the `#[macro_use]` on the module/import? +error: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:20:14 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:32:14 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + error: cannot find macro `in_block` in this scope --> $DIR/key-value-expansion-scope.rs:43:14 | @@ -118,5 +150,5 @@ LL | #![doc = in_block!()] | = help: have you added the `#[macro_use]` on the module/import? -error: aborting due to 15 previous errors +error: aborting due to 19 previous errors diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index 815013733a98b..609526150ba2e 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -1,47 +1,47 @@ error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:7:1 + --> $DIR/feature-gate-optimize_attribute.rs:2:1 | -LL | #[optimize(size)] - | ^^^^^^^^^^^^^^^^^ +LL | #![optimize(speed)] + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:10:1 + --> $DIR/feature-gate-optimize_attribute.rs:4:1 | -LL | #[optimize(speed)] - | ^^^^^^^^^^^^^^^^^^ +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:13:1 + --> $DIR/feature-gate-optimize_attribute.rs:7:1 | -LL | #[optimize(banana)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:4:1 + --> $DIR/feature-gate-optimize_attribute.rs:10:1 | -LL | #[optimize(size)] - | ^^^^^^^^^^^^^^^^^ +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:2:1 + --> $DIR/feature-gate-optimize_attribute.rs:13:1 | -LL | #![optimize(speed)] +LL | #[optimize(banana)] | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #54882 for more information diff --git a/tests/ui/feature-gates/feature-gate-staged_api.stderr b/tests/ui/feature-gates/feature-gate-staged_api.stderr index 1a9fcb02b0dee..86ba509ae7d10 100644 --- a/tests/ui/feature-gates/feature-gate-staged_api.stderr +++ b/tests/ui/feature-gates/feature-gate-staged_api.stderr @@ -1,15 +1,15 @@ -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/feature-gate-staged_api.rs:8:1 - | -LL | #[stable(feature = "a", since = "3.3.3")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/feature-gate-staged_api.rs:1:1 | LL | #![stable(feature = "a", since = "3.3.3")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-staged_api.rs:8:1 + | +LL | #[stable(feature = "a", since = "3.3.3")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 88732f75cb4e1..fdf4ec2254499 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -42,6 +42,20 @@ warning: unknown lint: `x5100` LL | #![deny(x5100)] | ^^^^^ +warning: use of deprecated attribute `crate_id`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 + | +LL | #![crate_id = "10"] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated attribute `no_start`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 + | +LL | #![no_start] + | ^^^^^^^^^^^^ help: remove this attribute + warning: unknown lint: `x5400` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8 | @@ -1178,4 +1192,3 @@ LL | #![feature(rust1)] = note: `#[warn(stable_features)]` on by default warning: 173 warnings emitted - diff --git a/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr index 677fef3a926b5..bac3b018e2e43 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr @@ -1,3 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:7:1 + | +LL | #![stable()] + | ^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:10:1 + | +LL | #[stable()] + | ^^^^^^^^^^^ + error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-stable.rs:14:9 | @@ -28,18 +40,6 @@ error[E0734]: stability attributes may not be used outside of the standard libra LL | #[stable()] | ^^^^^^^^^^^ -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-stable.rs:10:1 - | -LL | #[stable()] - | ^^^^^^^^^^^ - -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-stable.rs:7:1 - | -LL | #![stable()] - | ^^^^^^^^^^^^ - error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr index a2f361878c6db..9ea60f838008c 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr @@ -1,3 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:7:1 + | +LL | #![unstable()] + | ^^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:10:1 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-unstable.rs:14:9 | @@ -28,18 +40,6 @@ error[E0734]: stability attributes may not be used outside of the standard libra LL | #[unstable()] | ^^^^^^^^^^^^^ -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-unstable.rs:10:1 - | -LL | #[unstable()] - | ^^^^^^^^^^^^^ - -error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-43106-gating-of-unstable.rs:7:1 - | -LL | #![unstable()] - | ^^^^^^^^^^^^^^ - error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr index 0f4ddc065a742..2690c68a83415 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -4,6 +4,21 @@ error[E0425]: cannot find value `NonExistent` in this scope LL | NonExistent; | ^^^^^^^^^^^ not found in this scope +error[E0659]: `feature` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:3:4 + | +LL | #![feature(decl_macro)] + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `feature` could refer to a built-in attribute +note: `feature` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::feature` to refer to this attribute macro unambiguously + error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:9:3 | @@ -79,21 +94,6 @@ LL | use deny as allow; | ^^^^^^^^^^^^^ = help: use `crate::allow` to refer to this built-in attribute unambiguously -error[E0659]: `feature` is ambiguous - --> $DIR/ambiguous-builtin-attrs.rs:3:4 - | -LL | #![feature(decl_macro)] - | ^^^^^^^ ambiguous name - | - = note: ambiguous because of a name conflict with a builtin attribute - = note: `feature` could refer to a built-in attribute -note: `feature` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:6:5 - | -LL | use builtin_attrs::*; - | ^^^^^^^^^^^^^^^^ - = help: use `crate::feature` to refer to this attribute macro unambiguously - error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/ambiguous-builtin-attrs.rs:20:39 | diff --git a/tests/ui/stability-attribute/issue-106589.stderr b/tests/ui/stability-attribute/issue-106589.stderr index ccf3f7164e3e1..c14ad2da04b69 100644 --- a/tests/ui/stability-attribute/issue-106589.stderr +++ b/tests/ui/stability-attribute/issue-106589.stderr @@ -1,13 +1,13 @@ error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-106589.rs:6:1 + --> $DIR/issue-106589.rs:3:1 | -LL | #[unstable(feature = "foo", issue = "none")] +LL | #![stable(feature = "foo", since = "1.0.0")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0734]: stability attributes may not be used outside of the standard library - --> $DIR/issue-106589.rs:3:1 + --> $DIR/issue-106589.rs:6:1 | -LL | #![stable(feature = "foo", since = "1.0.0")] +LL | #[unstable(feature = "foo", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors From c4c7859e40efcfff640af442fb5d1fab3718d374 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 18 Jun 2024 16:45:50 +0300 Subject: [PATCH 2/2] resolve: Implement a lint for out-of-scope use of `macro_rules` --- compiler/rustc_lint/messages.ftl | 3 + .../rustc_lint/src/context/diagnostics.rs | 3 + compiler/rustc_lint/src/lints.rs | 7 + compiler/rustc_lint_defs/src/builtin.rs | 39 ++++++ compiler/rustc_lint_defs/src/lib.rs | 3 + .../rustc_resolve/src/build_reduced_graph.rs | 19 ++- compiler/rustc_resolve/src/macros.rs | 80 +++++++++-- .../key-value-expansion-scope-pass.rs | 18 +++ .../attributes/key-value-expansion-scope.rs | 19 ++- .../key-value-expansion-scope.stderr | 125 ++++++++++++------ ...issue-43106-gating-of-builtin-attrs.stderr | 19 +-- .../proc-macro/ambiguous-builtin-attrs.stderr | 30 ++--- 12 files changed, 273 insertions(+), 92 deletions(-) create mode 100644 tests/ui/attributes/key-value-expansion-scope-pass.rs diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index eac5083ffbf0c..46cf87d1e3c17 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -604,6 +604,9 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro .suggestion = use pat_param to preserve semantics +lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope + .help = import `macro_rules` with `use` to make it callable above its definition + lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index adb2a3275c0aa..05e075205c4b7 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -434,5 +434,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::InnerAttributeUnstable::CustomInnerAttribute } .decorate_lint(diag), + BuiltinLintDiag::OutOfScopeMacroCalls { path } => { + lints::OutOfScopeMacroCalls { path }.decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 6df3a11deb00b..14084405d0ee1 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2911,3 +2911,10 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = ")")] pub right: Span, } + +#[derive(LintDiagnostic)] +#[diag(lint_out_of_scope_macro_calls)] +#[help] +pub struct OutOfScopeMacroCalls { + pub path: String, +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 265779c937474..a023d6161df0c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4945,3 +4945,42 @@ declare_lint! { reference: "issue #123757 ", }; } + +declare_lint! { + /// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope, + /// above their definition, which may happen in key-value attributes. + /// + /// ### Example + /// + /// ```rust + /// #![doc = in_root!()] + /// + /// macro_rules! in_root { () => { "" } } + /// + /// fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The scope in which a `macro_rules` item is visible starts at that item and continues + /// below it. This is more similar to `let` than to other items, which are in scope both above + /// and below their definition. + /// Due to a bug `macro_rules` were accidentally in scope inside some key-value attributes + /// above their definition. The lint catches such cases. + /// To address the issue turn the `macro_rules` into a regularly scoped item by importing it + /// with `use`. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub OUT_OF_SCOPE_MACRO_CALLS, + Warn, + "detects out of scope calls to `macro_rules` in key-value attributes", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #124535 ", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f33aadfbbc84d..b44eb25216770 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -744,6 +744,9 @@ pub enum BuiltinLintDiag { InnerAttributeUnstable { is_macro: bool, }, + OutOfScopeMacroCalls { + path: String, + }, } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e035749fc39ee..4e0f2792d9749 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -14,7 +14,7 @@ use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, Modul use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError}; use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError}; -use rustc_ast::visit::{self, AssocCtxt, Visitor}; +use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_attr as attr; @@ -1313,7 +1313,17 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { _ => { let orig_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_item(item); - visit::walk_item(self, item); + match item.kind { + ItemKind::Mod(..) => { + // Visit attributes after items for backward compatibility. + // This way they can use `macro_rules` defined later. + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + item.kind.walk(item, AssocCtxt::Trait, self); + visit::walk_list!(self, visit_attribute, &item.attrs); + } + _ => visit::walk_item(self, item), + } match item.kind { ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => { self.parent_scope.macro_rules @@ -1514,7 +1524,10 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { if krate.is_placeholder { self.visit_invoc_in_module(krate.id); } else { - visit::walk_crate(self, krate); + // Visit attributes after items for backward compatibility. + // This way they can use `macro_rules` defined later. + visit::walk_list!(self, visit_item, &krate.items); + visit::walk_list!(self, visit_attribute, &krate.attrs); self.contains_macro_use(&krate.attrs); } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 87794d11cea9c..109cd3a9b77f1 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -5,7 +5,7 @@ use crate::errors::CannotDetermineMacroResolution; use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope}; use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive}; use crate::Namespace::*; -use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, Used}; +use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, NameBindingKind, Used}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::expand::StrippedCfgItem; @@ -18,15 +18,18 @@ use rustc_errors::{Applicability, StashKey}; use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; -use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; +use rustc_expand::expand::{ + AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion, +}; use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; use rustc_middle::ty::{TyCtxt, Visibility}; -use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; -use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; -use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; +use rustc_session::lint::builtin::{ + LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, SOFT_UNSTABLE, + UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACROS, UNUSED_MACRO_RULES, +}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; use rustc_span::edit_distance::edit_distance; @@ -288,6 +291,16 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { let parent_scope = &ParentScope { derives, ..parent_scope }; let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion(); let node_id = invoc.expansion_data.lint_node_id; + // This is a heuristic, but it's good enough for the lint. + let looks_like_invoc_in_mod_inert_attr = self + .invocation_parents + .get(&invoc_id) + .or_else(|| self.invocation_parents.get(&eager_expansion_root)) + .map(|&(mod_def_id, _)| mod_def_id) + .filter(|&mod_def_id| { + invoc.fragment_kind == AstFragmentKind::Expr + && self.tcx.def_kind(mod_def_id) == DefKind::Mod + }); let (ext, res) = self.smart_resolve_macro_path( path, kind, @@ -298,6 +311,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { force, soft_custom_inner_attributes_gate(path, invoc), deleg_impl, + looks_like_invoc_in_mod_inert_attr, )?; let span = invoc.span(); @@ -520,6 +534,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { force: bool, soft_custom_inner_attributes_gate: bool, deleg_impl: Option, + invoc_in_mod_inert_attr: Option, ) -> Result<(Lrc, Res), Indeterminate> { let (ext, res) = match self.resolve_macro_or_delegation_path( path, @@ -528,6 +543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true, force, deleg_impl, + invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)), ) { Ok((Some(ext), res)) => (ext, res), Ok((None, res)) => (self.dummy_ext(kind), res), @@ -682,20 +698,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trace: bool, force: bool, ) -> Result<(Option>, Res), Determinacy> { - self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None) + self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None) } fn resolve_macro_or_delegation_path( &mut self, - path: &ast::Path, + ast_path: &ast::Path, kind: Option, parent_scope: &ParentScope<'a>, trace: bool, force: bool, deleg_impl: Option, + invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, ) -> Result<(Option>, Res), Determinacy> { - let path_span = path.span; - let mut path = Segment::from_path(path); + let path_span = ast_path.span; + let mut path = Segment::from_path(ast_path); // Possibly apply the macro helper hack if deleg_impl.is_none() @@ -761,6 +778,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let res = binding.map(|binding| binding.res()); self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span); + self.report_out_of_scope_macro_calls( + ast_path, + parent_scope, + invoc_in_mod_inert_attr, + binding.ok(), + ); res }; @@ -1013,6 +1036,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + fn report_out_of_scope_macro_calls( + &mut self, + path: &ast::Path, + parent_scope: &ParentScope<'a>, + invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, + binding: Option>, + ) { + if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr + && let Some(binding) = binding + // This is a `macro_rules` itself, not some import. + && let NameBindingKind::Res(res) = binding.kind + && let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res + // And the `macro_rules` is defined inside the attribute's module, + // so it cannot be in scope unless imported. + && self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id()) + { + // Try to resolve our ident ignoring `macro_rules` scopes. + // If such resolution is successful and gives the same result + // (e.g. if the macro is re-imported), then silence the lint. + let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty); + let fallback_binding = self.early_resolve_ident_in_lexical_scope( + path.segments[0].ident, + ScopeSet::Macro(MacroKind::Bang), + &ParentScope { macro_rules: no_macro_rules, ..*parent_scope }, + None, + false, + None, + ); + if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) { + self.tcx.sess.psess.buffer_lint( + OUT_OF_SCOPE_MACRO_CALLS, + path.span, + node_id, + BuiltinLintDiag::OutOfScopeMacroCalls { path: pprust::path_to_string(path) }, + ); + } + } + } + pub(crate) fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) { // Reserve some names that are not quite covered by the general check // performed on `Resolver::builtin_attrs`. diff --git a/tests/ui/attributes/key-value-expansion-scope-pass.rs b/tests/ui/attributes/key-value-expansion-scope-pass.rs new file mode 100644 index 0000000000000..6b1f4e5bd4bf0 --- /dev/null +++ b/tests/ui/attributes/key-value-expansion-scope-pass.rs @@ -0,0 +1,18 @@ +// Imports suppress the `out_of_scope_macro_calls` lint. + +//@ check-pass +//@ edition:2018 + +#![doc = in_root!()] + +macro_rules! in_root { () => { "" } } +use in_root; + +mod macros_stay { + #![doc = in_mod!()] + + macro_rules! in_mod { () => { "" } } + use in_mod; +} + +fn main() {} diff --git a/tests/ui/attributes/key-value-expansion-scope.rs b/tests/ui/attributes/key-value-expansion-scope.rs index 147e9bdbe241c..b6eab1571d490 100644 --- a/tests/ui/attributes/key-value-expansion-scope.rs +++ b/tests/ui/attributes/key-value-expansion-scope.rs @@ -1,6 +1,8 @@ -#![doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope +#![doc = in_root!()] //~ WARN cannot find macro `in_root` in this scope + //~| WARN this was previously accepted by the compiler #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope -#![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope +#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope + //~| WARN this was previously accepted by the compiler #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope #[doc = in_root!()] //~ ERROR cannot find macro `in_root` in this scope @@ -16,8 +18,11 @@ fn before() { macro_rules! in_root { () => { "" } } +#[doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope + //~| WARN this was previously accepted by the compiler mod macros_stay { - #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope + #![doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope + //~| WARN this was previously accepted by the compiler macro_rules! in_mod { () => { "" } } @@ -28,8 +33,11 @@ mod macros_stay { } #[macro_use] +#[doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope + //~| WARN this was previously accepted by the compiler mod macros_escape { - #![doc = in_mod_escape!()] //~ ERROR cannot find macro `in_mod_escape` in this scope + #![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope + //~| WARN this was previously accepted by the compiler macro_rules! in_mod_escape { () => { "" } } @@ -39,8 +47,9 @@ mod macros_escape { } } +#[doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope fn block() { - #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope + #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope macro_rules! in_block { () => { "" } } diff --git a/tests/ui/attributes/key-value-expansion-scope.stderr b/tests/ui/attributes/key-value-expansion-scope.stderr index c7713a0ee09f2..d22fef7dd251e 100644 --- a/tests/ui/attributes/key-value-expansion-scope.stderr +++ b/tests/ui/attributes/key-value-expansion-scope.stderr @@ -1,29 +1,13 @@ -error: cannot find macro `in_root` in this scope - --> $DIR/key-value-expansion-scope.rs:1:10 - | -LL | #![doc = in_root!()] - | ^^^^^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:2:10 + --> $DIR/key-value-expansion-scope.rs:3:10 | LL | #![doc = in_mod!()] | ^^^^^^ | = help: have you added the `#[macro_use]` on the module/import? -error: cannot find macro `in_mod_escape` in this scope - --> $DIR/key-value-expansion-scope.rs:3:10 - | -LL | #![doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:4:10 + --> $DIR/key-value-expansion-scope.rs:6:10 | LL | #![doc = in_block!()] | ^^^^^^^^ @@ -31,7 +15,7 @@ LL | #![doc = in_block!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_root` in this scope - --> $DIR/key-value-expansion-scope.rs:6:9 + --> $DIR/key-value-expansion-scope.rs:8:9 | LL | #[doc = in_root!()] | ^^^^^^^ @@ -39,7 +23,7 @@ LL | #[doc = in_root!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:7:9 + --> $DIR/key-value-expansion-scope.rs:9:9 | LL | #[doc = in_mod!()] | ^^^^^^ @@ -47,7 +31,7 @@ LL | #[doc = in_mod!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod_escape` in this scope - --> $DIR/key-value-expansion-scope.rs:8:9 + --> $DIR/key-value-expansion-scope.rs:10:9 | LL | #[doc = in_mod_escape!()] | ^^^^^^^^^^^^^ @@ -55,7 +39,7 @@ LL | #[doc = in_mod_escape!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:9:9 + --> $DIR/key-value-expansion-scope.rs:11:9 | LL | #[doc = in_block!()] | ^^^^^^^^ @@ -63,7 +47,7 @@ LL | #[doc = in_block!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_root` in this scope - --> $DIR/key-value-expansion-scope.rs:11:14 + --> $DIR/key-value-expansion-scope.rs:13:14 | LL | #![doc = in_root!()] | ^^^^^^^ @@ -71,7 +55,7 @@ LL | #![doc = in_root!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:12:14 + --> $DIR/key-value-expansion-scope.rs:14:14 | LL | #![doc = in_mod!()] | ^^^^^^ @@ -79,7 +63,7 @@ LL | #![doc = in_mod!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod_escape` in this scope - --> $DIR/key-value-expansion-scope.rs:13:14 + --> $DIR/key-value-expansion-scope.rs:15:14 | LL | #![doc = in_mod_escape!()] | ^^^^^^^^^^^^^ @@ -87,31 +71,23 @@ LL | #![doc = in_mod_escape!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:14:14 + --> $DIR/key-value-expansion-scope.rs:16:14 | LL | #![doc = in_block!()] | ^^^^^^^^ | = help: have you added the `#[macro_use]` on the module/import? -error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:20:14 - | -LL | #![doc = in_mod!()] - | ^^^^^^ - | - = help: have you added the `#[macro_use]` on the module/import? - -error: cannot find macro `in_mod_escape` in this scope - --> $DIR/key-value-expansion-scope.rs:32:14 +error: cannot find macro `in_block` in this scope + --> $DIR/key-value-expansion-scope.rs:50:9 | -LL | #![doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ +LL | #[doc = in_block!()] + | ^^^^^^^^ | = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:43:14 + --> $DIR/key-value-expansion-scope.rs:52:14 | LL | #![doc = in_block!()] | ^^^^^^^^ @@ -119,7 +95,7 @@ LL | #![doc = in_block!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:54:9 + --> $DIR/key-value-expansion-scope.rs:63:9 | LL | #[doc = in_mod!()] | ^^^^^^ @@ -127,7 +103,7 @@ LL | #[doc = in_mod!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:56:9 + --> $DIR/key-value-expansion-scope.rs:65:9 | LL | #[doc = in_block!()] | ^^^^^^^^ @@ -135,7 +111,7 @@ LL | #[doc = in_block!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_mod` in this scope - --> $DIR/key-value-expansion-scope.rs:59:14 + --> $DIR/key-value-expansion-scope.rs:68:14 | LL | #![doc = in_mod!()] | ^^^^^^ @@ -143,12 +119,73 @@ LL | #![doc = in_mod!()] = help: have you added the `#[macro_use]` on the module/import? error: cannot find macro `in_block` in this scope - --> $DIR/key-value-expansion-scope.rs:61:14 + --> $DIR/key-value-expansion-scope.rs:70:14 | LL | #![doc = in_block!()] | ^^^^^^^^ | = help: have you added the `#[macro_use]` on the module/import? -error: aborting due to 19 previous errors +warning: cannot find macro `in_root` in this scope + --> $DIR/key-value-expansion-scope.rs:1:10 + | +LL | #![doc = in_root!()] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + = note: `#[warn(out_of_scope_macro_calls)]` on by default + +warning: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:4:10 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + +warning: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:21:9 + | +LL | #[doc = in_mod!()] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + +warning: cannot find macro `in_mod` in this scope + --> $DIR/key-value-expansion-scope.rs:24:14 + | +LL | #![doc = in_mod!()] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + +warning: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:36:9 + | +LL | #[doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + +warning: cannot find macro `in_mod_escape` in this scope + --> $DIR/key-value-expansion-scope.rs:39:14 + | +LL | #![doc = in_mod_escape!()] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #124535 + = help: import `macro_rules` with `use` to make it callable above its definition + +error: aborting due to 16 previous errors; 6 warnings emitted diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index fdf4ec2254499..e43cef7c15078 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -42,7 +42,7 @@ warning: unknown lint: `x5100` LL | #![deny(x5100)] | ^^^^^ -warning: use of deprecated attribute `crate_id`: no longer used. +warning: use of deprecated attribute `crate_id`: no longer used --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 | LL | #![crate_id = "10"] @@ -50,7 +50,7 @@ LL | #![crate_id = "10"] | = note: `#[warn(deprecated)]` on by default -warning: use of deprecated attribute `no_start`: no longer used. +warning: use of deprecated attribute `no_start`: no longer used --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 | LL | #![no_start] @@ -200,20 +200,6 @@ warning: unknown lint: `x5100` LL | #[deny(x5100)] impl S { } | ^^^^^ -warning: use of deprecated attribute `crate_id`: no longer used - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 - | -LL | #![crate_id = "10"] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: `#[warn(deprecated)]` on by default - -warning: use of deprecated attribute `no_start`: no longer used - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 - | -LL | #![no_start] - | ^^^^^^^^^^^^ help: remove this attribute - warning: `#[macro_export]` only has an effect on macro definitions --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1 | @@ -1192,3 +1178,4 @@ LL | #![feature(rust1)] = note: `#[warn(stable_features)]` on by default warning: 173 warnings emitted + diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr index 2690c68a83415..0f4ddc065a742 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -4,21 +4,6 @@ error[E0425]: cannot find value `NonExistent` in this scope LL | NonExistent; | ^^^^^^^^^^^ not found in this scope -error[E0659]: `feature` is ambiguous - --> $DIR/ambiguous-builtin-attrs.rs:3:4 - | -LL | #![feature(decl_macro)] - | ^^^^^^^ ambiguous name - | - = note: ambiguous because of a name conflict with a builtin attribute - = note: `feature` could refer to a built-in attribute -note: `feature` could also refer to the attribute macro imported here - --> $DIR/ambiguous-builtin-attrs.rs:6:5 - | -LL | use builtin_attrs::*; - | ^^^^^^^^^^^^^^^^ - = help: use `crate::feature` to refer to this attribute macro unambiguously - error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:9:3 | @@ -94,6 +79,21 @@ LL | use deny as allow; | ^^^^^^^^^^^^^ = help: use `crate::allow` to refer to this built-in attribute unambiguously +error[E0659]: `feature` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:3:4 + | +LL | #![feature(decl_macro)] + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `feature` could refer to a built-in attribute +note: `feature` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::feature` to refer to this attribute macro unambiguously + error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/ambiguous-builtin-attrs.rs:20:39 |