Skip to content

Commit d929a42

Browse files
committed
Auto merge of #125741 - petrochenkov:atvisord, r=davidtwco
ast: Standardize visiting order for attributes and node IDs This should only affect `macro_rules` scopes and order of diagnostics. Also add a deprecation lint for `macro_rules` called outside of their scope, like in #124535.
2 parents c2d2bb3 + c4c7859 commit d929a42

21 files changed

+412
-186
lines changed

compiler/rustc_ast/src/mut_visit.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
429429
) -> SmallVec<[PatField; 1]> {
430430
let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
431431
vis.visit_id(id);
432+
visit_attrs(attrs, vis);
432433
vis.visit_ident(ident);
433434
vis.visit_pat(pat);
434435
vis.visit_span(span);
435-
visit_attrs(attrs, vis);
436436
smallvec![fp]
437437
}
438438

@@ -443,8 +443,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
443443
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
444444
UseTreeKind::Nested { items, .. } => {
445445
for (tree, id) in items {
446-
vis.visit_use_tree(tree);
447446
vis.visit_id(id);
447+
vis.visit_use_tree(tree);
448448
}
449449
}
450450
UseTreeKind::Glob => {}
@@ -454,8 +454,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
454454

455455
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
456456
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
457-
visit_attrs(attrs, vis);
458457
vis.visit_id(id);
458+
visit_attrs(attrs, vis);
459459
vis.visit_pat(pat);
460460
visit_opt(guard, |guard| vis.visit_expr(guard));
461461
visit_opt(body, |body| vis.visit_expr(body));
@@ -548,10 +548,10 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
548548
visitor: &mut T,
549549
) -> SmallVec<[Variant; 1]> {
550550
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
551+
visitor.visit_id(id);
552+
visit_attrs(attrs, visitor);
551553
visitor.visit_ident(ident);
552554
visitor.visit_vis(vis);
553-
visit_attrs(attrs, visitor);
554-
visitor.visit_id(id);
555555
visitor.visit_variant_data(data);
556556
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
557557
visitor.visit_span(span);
@@ -565,8 +565,8 @@ fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mu
565565
fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
566566
vis.visit_span(span);
567567
for PathSegment { ident, id, args } in segments {
568-
vis.visit_ident(ident);
569568
vis.visit_id(id);
569+
vis.visit_ident(ident);
570570
visit_opt(args, |args| vis.visit_generic_args(args));
571571
}
572572
visit_lazy_tts(tokens, vis);
@@ -620,6 +620,7 @@ fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
620620
fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
621621
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
622622
vis.visit_id(id);
623+
visit_attrs(attrs, vis);
623624
vis.visit_pat(pat);
624625
visit_opt(ty, |ty| vis.visit_ty(ty));
625626
match kind {
@@ -634,7 +635,6 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
634635
}
635636
vis.visit_span(span);
636637
visit_opt(colon_sp, |sp| vis.visit_span(sp));
637-
visit_attrs(attrs, vis);
638638
visit_lazy_tts(tokens, vis);
639639
}
640640

@@ -894,9 +894,9 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
894894
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
895895
| CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
896896
| CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
897-
vis.visit_span(span);
898897
vis.visit_id(closure_id);
899898
vis.visit_id(return_impl_trait_id);
899+
vis.visit_span(span);
900900
}
901901
}
902902
}
@@ -932,8 +932,8 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
932932
vis.visit_lifetime(lt);
933933
}
934934
PreciseCapturingArg::Arg(path, id) => {
935-
vis.visit_path(path);
936935
vis.visit_id(id);
936+
vis.visit_path(path);
937937
}
938938
}
939939
}
@@ -944,11 +944,11 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
944944
) -> SmallVec<[GenericParam; 1]> {
945945
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
946946
vis.visit_id(id);
947+
visit_attrs(attrs, vis);
947948
vis.visit_ident(ident);
948949
if let Some(colon_span) = colon_span {
949950
vis.visit_span(colon_span);
950951
}
951-
visit_attrs(attrs, vis);
952952
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
953953
match kind {
954954
GenericParamKind::Lifetime => {}
@@ -1015,16 +1015,16 @@ fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T)
10151015
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
10161016
}
10171017
VariantData::Tuple(fields, id) => {
1018-
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
10191018
vis.visit_id(id);
1019+
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
10201020
}
10211021
VariantData::Unit(id) => vis.visit_id(id),
10221022
}
10231023
}
10241024

10251025
fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
1026-
vis.visit_path(path);
10271026
vis.visit_id(ref_id);
1027+
vis.visit_path(path);
10281028
}
10291029

10301030
fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
@@ -1039,12 +1039,12 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
10391039
visitor: &mut T,
10401040
) -> SmallVec<[FieldDef; 1]> {
10411041
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
1042+
visitor.visit_id(id);
1043+
visit_attrs(attrs, visitor);
10421044
visitor.visit_span(span);
10431045
visit_opt(ident, |ident| visitor.visit_ident(ident));
10441046
visitor.visit_vis(vis);
1045-
visitor.visit_id(id);
10461047
visitor.visit_ty(ty);
1047-
visit_attrs(attrs, visitor);
10481048
smallvec![fd]
10491049
}
10501050

@@ -1053,11 +1053,11 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
10531053
vis: &mut T,
10541054
) -> SmallVec<[ExprField; 1]> {
10551055
let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
1056+
vis.visit_id(id);
1057+
visit_attrs(attrs, vis);
10561058
vis.visit_ident(ident);
10571059
vis.visit_expr(expr);
1058-
vis.visit_id(id);
10591060
vis.visit_span(span);
1060-
visit_attrs(attrs, vis);
10611061
smallvec![f]
10621062
}
10631063

@@ -1429,6 +1429,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
14291429
Expr { kind, id, span, attrs, tokens }: &mut Expr,
14301430
vis: &mut T,
14311431
) {
1432+
vis.visit_id(id);
1433+
visit_attrs(attrs, vis);
14321434
match kind {
14331435
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
14341436
ExprKind::ConstBlock(anon_const) => {
@@ -1449,8 +1451,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
14491451
args: call_args,
14501452
span,
14511453
}) => {
1452-
vis.visit_ident(ident);
14531454
vis.visit_id(id);
1455+
vis.visit_ident(ident);
14541456
visit_opt(seg_args, |args| vis.visit_generic_args(args));
14551457
vis.visit_method_receiver_expr(receiver);
14561458
visit_thin_exprs(call_args, vis);
@@ -1601,9 +1603,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
16011603
ExprKind::TryBlock(body) => vis.visit_block(body),
16021604
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
16031605
}
1604-
vis.visit_id(id);
16051606
vis.visit_span(span);
1606-
visit_attrs(attrs, vis);
16071607
visit_lazy_tts(tokens, vis);
16081608
}
16091609

@@ -1645,8 +1645,8 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
16451645
StmtKind::Empty => smallvec![StmtKind::Empty],
16461646
StmtKind::MacCall(mut mac) => {
16471647
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
1648-
vis.visit_mac_call(mac_);
16491648
visit_attrs(attrs, vis);
1649+
vis.visit_mac_call(mac_);
16501650
visit_lazy_tts(tokens, vis);
16511651
smallvec![StmtKind::MacCall(mac)]
16521652
}
@@ -1657,8 +1657,8 @@ fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
16571657
match &mut visibility.kind {
16581658
VisibilityKind::Public | VisibilityKind::Inherited => {}
16591659
VisibilityKind::Restricted { path, id, shorthand: _ } => {
1660-
vis.visit_path(path);
16611660
vis.visit_id(id);
1661+
vis.visit_path(path);
16621662
}
16631663
}
16641664
vis.visit_span(&mut visibility.span);

compiler/rustc_ast/src/visit.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ pub trait Visitor<'ast>: Sized {
298298
}
299299

300300
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
301-
walk_list!(visitor, visit_item, &krate.items);
302301
walk_list!(visitor, visit_attribute, &krate.attrs);
302+
walk_list!(visitor, visit_item, &krate.items);
303303
V::Result::output()
304304
}
305305

@@ -462,25 +462,25 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -
462462
where
463463
V: Visitor<'a>,
464464
{
465+
walk_list!(visitor, visit_attribute, &variant.attrs);
465466
try_visit!(visitor.visit_ident(variant.ident));
466467
try_visit!(visitor.visit_vis(&variant.vis));
467468
try_visit!(visitor.visit_variant_data(&variant.data));
468469
visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
469-
walk_list!(visitor, visit_attribute, &variant.attrs);
470470
V::Result::output()
471471
}
472472

473473
pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
474+
walk_list!(visitor, visit_attribute, &f.attrs);
474475
try_visit!(visitor.visit_expr(&f.expr));
475476
try_visit!(visitor.visit_ident(f.ident));
476-
walk_list!(visitor, visit_attribute, &f.attrs);
477477
V::Result::output()
478478
}
479479

480480
pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
481+
walk_list!(visitor, visit_attribute, &fp.attrs);
481482
try_visit!(visitor.visit_ident(fp.ident));
482483
try_visit!(visitor.visit_pat(&fp.pat));
483-
walk_list!(visitor, visit_attribute, &fp.attrs);
484484
V::Result::output()
485485
}
486486

@@ -722,8 +722,8 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
722722
visitor: &mut V,
723723
param: &'a GenericParam,
724724
) -> V::Result {
725-
try_visit!(visitor.visit_ident(param.ident));
726725
walk_list!(visitor, visit_attribute, &param.attrs);
726+
try_visit!(visitor.visit_ident(param.ident));
727727
walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
728728
match &param.kind {
729729
GenericParamKind::Lifetime => (),
@@ -882,10 +882,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
882882
ctxt: AssocCtxt,
883883
) -> V::Result {
884884
let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
885+
walk_list!(visitor, visit_attribute, attrs);
885886
try_visit!(visitor.visit_vis(vis));
886887
try_visit!(visitor.visit_ident(ident));
887888
try_visit!(kind.walk(item, ctxt, visitor));
888-
walk_list!(visitor, visit_attribute, attrs);
889889
V::Result::output()
890890
}
891891

@@ -898,10 +898,10 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(
898898
}
899899

900900
pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
901+
walk_list!(visitor, visit_attribute, &field.attrs);
901902
try_visit!(visitor.visit_vis(&field.vis));
902903
visit_opt!(visitor, visit_ident, field.ident);
903904
try_visit!(visitor.visit_ty(&field.ty));
904-
walk_list!(visitor, visit_attribute, &field.attrs);
905905
V::Result::output()
906906
}
907907

@@ -918,8 +918,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V:
918918
StmtKind::Empty => {}
919919
StmtKind::MacCall(mac) => {
920920
let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
921-
try_visit!(visitor.visit_mac_call(mac));
922921
walk_list!(visitor, visit_attribute, attrs);
922+
try_visit!(visitor.visit_mac_call(mac));
923923
}
924924
}
925925
V::Result::output()
@@ -1141,10 +1141,10 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::R
11411141
}
11421142

11431143
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
1144+
walk_list!(visitor, visit_attribute, &arm.attrs);
11441145
try_visit!(visitor.visit_pat(&arm.pat));
11451146
visit_opt!(visitor, visit_expr, &arm.guard);
11461147
visit_opt!(visitor, visit_expr, &arm.body);
1147-
walk_list!(visitor, visit_attribute, &arm.attrs);
11481148
V::Result::output()
11491149
}
11501150

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,9 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound
604604
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
605605
.suggestion = use pat_param to preserve semantics
606606
607+
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope
608+
.help = import `macro_rules` with `use` to make it callable above its definition
609+
607610
lint_overflowing_bin_hex = literal out of range for `{$ty}`
608611
.negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
609612
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`

compiler/rustc_lint/src/context/diagnostics.rs

+3
Original file line numberDiff line numberDiff line change
@@ -434,5 +434,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
434434
lints::InnerAttributeUnstable::CustomInnerAttribute
435435
}
436436
.decorate_lint(diag),
437+
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
438+
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
439+
}
437440
}
438441
}

compiler/rustc_lint/src/lints.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2911,3 +2911,10 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
29112911
#[suggestion_part(code = ")")]
29122912
pub right: Span,
29132913
}
2914+
2915+
#[derive(LintDiagnostic)]
2916+
#[diag(lint_out_of_scope_macro_calls)]
2917+
#[help]
2918+
pub struct OutOfScopeMacroCalls {
2919+
pub path: String,
2920+
}

compiler/rustc_lint_defs/src/builtin.rs

+39
Original file line numberDiff line numberDiff line change
@@ -4945,3 +4945,42 @@ declare_lint! {
49454945
reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
49464946
};
49474947
}
4948+
4949+
declare_lint! {
4950+
/// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope,
4951+
/// above their definition, which may happen in key-value attributes.
4952+
///
4953+
/// ### Example
4954+
///
4955+
/// ```rust
4956+
/// #![doc = in_root!()]
4957+
///
4958+
/// macro_rules! in_root { () => { "" } }
4959+
///
4960+
/// fn main() {}
4961+
/// ```
4962+
///
4963+
/// {{produces}}
4964+
///
4965+
/// ### Explanation
4966+
///
4967+
/// The scope in which a `macro_rules` item is visible starts at that item and continues
4968+
/// below it. This is more similar to `let` than to other items, which are in scope both above
4969+
/// and below their definition.
4970+
/// Due to a bug `macro_rules` were accidentally in scope inside some key-value attributes
4971+
/// above their definition. The lint catches such cases.
4972+
/// To address the issue turn the `macro_rules` into a regularly scoped item by importing it
4973+
/// with `use`.
4974+
///
4975+
/// This is a [future-incompatible] lint to transition this to a
4976+
/// hard error in the future.
4977+
///
4978+
/// [future-incompatible]: ../index.md#future-incompatible-lints
4979+
pub OUT_OF_SCOPE_MACRO_CALLS,
4980+
Warn,
4981+
"detects out of scope calls to `macro_rules` in key-value attributes",
4982+
@future_incompatible = FutureIncompatibleInfo {
4983+
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
4984+
reference: "issue #124535 <https://github.com/rust-lang/rust/issues/124535>",
4985+
};
4986+
}

compiler/rustc_lint_defs/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,9 @@ pub enum BuiltinLintDiag {
744744
InnerAttributeUnstable {
745745
is_macro: bool,
746746
},
747+
OutOfScopeMacroCalls {
748+
path: String,
749+
},
747750
}
748751

749752
/// Lints that are buffered up early on in the `Session` before the

0 commit comments

Comments
 (0)