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 https://github.com/rust-lang/rust/issues/124535.
This commit is contained in:
bors 2024-06-25 11:48:14 +00:00
commit d929a42a66
21 changed files with 426 additions and 200 deletions

View File

@ -429,10 +429,10 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
) -> SmallVec<[PatField; 1]> { ) -> SmallVec<[PatField; 1]> {
let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp; let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
vis.visit_id(id); vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_ident(ident); vis.visit_ident(ident);
vis.visit_pat(pat); vis.visit_pat(pat);
vis.visit_span(span); vis.visit_span(span);
visit_attrs(attrs, vis);
smallvec![fp] smallvec![fp]
} }
@ -443,8 +443,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
UseTreeKind::Nested { items, .. } => { UseTreeKind::Nested { items, .. } => {
for (tree, id) in items { for (tree, id) in items {
vis.visit_use_tree(tree);
vis.visit_id(id); vis.visit_id(id);
vis.visit_use_tree(tree);
} }
} }
UseTreeKind::Glob => {} UseTreeKind::Glob => {}
@ -454,8 +454,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
visit_attrs(attrs, vis);
vis.visit_id(id); vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_pat(pat); vis.visit_pat(pat);
visit_opt(guard, |guard| vis.visit_expr(guard)); visit_opt(guard, |guard| vis.visit_expr(guard));
visit_opt(body, |body| vis.visit_expr(body)); visit_opt(body, |body| vis.visit_expr(body));
@ -548,10 +548,10 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
visitor: &mut T, visitor: &mut T,
) -> SmallVec<[Variant; 1]> { ) -> SmallVec<[Variant; 1]> {
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; 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_ident(ident);
visitor.visit_vis(vis); visitor.visit_vis(vis);
visit_attrs(attrs, visitor);
visitor.visit_id(id);
visitor.visit_variant_data(data); visitor.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
visitor.visit_span(span); visitor.visit_span(span);
@ -565,8 +565,8 @@ fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mu
fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) { fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
vis.visit_span(span); vis.visit_span(span);
for PathSegment { ident, id, args } in segments { for PathSegment { ident, id, args } in segments {
vis.visit_ident(ident);
vis.visit_id(id); vis.visit_id(id);
vis.visit_ident(ident);
visit_opt(args, |args| vis.visit_generic_args(args)); visit_opt(args, |args| vis.visit_generic_args(args));
} }
visit_lazy_tts(tokens, vis); visit_lazy_tts(tokens, vis);
@ -620,6 +620,7 @@ fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) { fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
vis.visit_id(id); vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_pat(pat); vis.visit_pat(pat);
visit_opt(ty, |ty| vis.visit_ty(ty)); visit_opt(ty, |ty| vis.visit_ty(ty));
match kind { match kind {
@ -634,7 +635,6 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
} }
vis.visit_span(span); vis.visit_span(span);
visit_opt(colon_sp, |sp| vis.visit_span(sp)); visit_opt(colon_sp, |sp| vis.visit_span(sp));
visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis); visit_lazy_tts(tokens, vis);
} }
@ -894,9 +894,9 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
CoroutineKind::Async { span, closure_id, return_impl_trait_id } CoroutineKind::Async { span, closure_id, return_impl_trait_id }
| CoroutineKind::Gen { 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 } => { | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
vis.visit_span(span);
vis.visit_id(closure_id); vis.visit_id(closure_id);
vis.visit_id(return_impl_trait_id); vis.visit_id(return_impl_trait_id);
vis.visit_span(span);
} }
} }
} }
@ -932,8 +932,8 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
vis.visit_lifetime(lt); vis.visit_lifetime(lt);
} }
PreciseCapturingArg::Arg(path, id) => { PreciseCapturingArg::Arg(path, id) => {
vis.visit_path(path);
vis.visit_id(id); vis.visit_id(id);
vis.visit_path(path);
} }
} }
} }
@ -944,11 +944,11 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
) -> SmallVec<[GenericParam; 1]> { ) -> SmallVec<[GenericParam; 1]> {
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param; let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
vis.visit_id(id); vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_ident(ident); vis.visit_ident(ident);
if let Some(colon_span) = colon_span { if let Some(colon_span) = colon_span {
vis.visit_span(colon_span); vis.visit_span(colon_span);
} }
visit_attrs(attrs, vis);
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
match kind { match kind {
GenericParamKind::Lifetime => {} GenericParamKind::Lifetime => {}
@ -1015,16 +1015,16 @@ fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T)
fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
} }
VariantData::Tuple(fields, id) => { VariantData::Tuple(fields, id) => {
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
vis.visit_id(id); vis.visit_id(id);
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
} }
VariantData::Unit(id) => vis.visit_id(id), VariantData::Unit(id) => vis.visit_id(id),
} }
} }
fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) { fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
vis.visit_path(path);
vis.visit_id(ref_id); vis.visit_id(ref_id);
vis.visit_path(path);
} }
fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) { 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>(
visitor: &mut T, visitor: &mut T,
) -> SmallVec<[FieldDef; 1]> { ) -> SmallVec<[FieldDef; 1]> {
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd; let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
visitor.visit_id(id);
visit_attrs(attrs, visitor);
visitor.visit_span(span); visitor.visit_span(span);
visit_opt(ident, |ident| visitor.visit_ident(ident)); visit_opt(ident, |ident| visitor.visit_ident(ident));
visitor.visit_vis(vis); visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty); visitor.visit_ty(ty);
visit_attrs(attrs, visitor);
smallvec![fd] smallvec![fd]
} }
@ -1053,11 +1053,11 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
vis: &mut T, vis: &mut T,
) -> SmallVec<[ExprField; 1]> { ) -> SmallVec<[ExprField; 1]> {
let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f; 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_ident(ident);
vis.visit_expr(expr); vis.visit_expr(expr);
vis.visit_id(id);
vis.visit_span(span); vis.visit_span(span);
visit_attrs(attrs, vis);
smallvec![f] smallvec![f]
} }
@ -1429,6 +1429,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
Expr { kind, id, span, attrs, tokens }: &mut Expr, Expr { kind, id, span, attrs, tokens }: &mut Expr,
vis: &mut T, vis: &mut T,
) { ) {
vis.visit_id(id);
visit_attrs(attrs, vis);
match kind { match kind {
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis), ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
ExprKind::ConstBlock(anon_const) => { ExprKind::ConstBlock(anon_const) => {
@ -1449,8 +1451,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
args: call_args, args: call_args,
span, span,
}) => { }) => {
vis.visit_ident(ident);
vis.visit_id(id); vis.visit_id(id);
vis.visit_ident(ident);
visit_opt(seg_args, |args| vis.visit_generic_args(args)); visit_opt(seg_args, |args| vis.visit_generic_args(args));
vis.visit_method_receiver_expr(receiver); vis.visit_method_receiver_expr(receiver);
visit_thin_exprs(call_args, vis); visit_thin_exprs(call_args, vis);
@ -1601,9 +1603,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
ExprKind::TryBlock(body) => vis.visit_block(body), ExprKind::TryBlock(body) => vis.visit_block(body),
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {} ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
} }
vis.visit_id(id);
vis.visit_span(span); vis.visit_span(span);
visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis); visit_lazy_tts(tokens, vis);
} }
@ -1645,8 +1645,8 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::Empty => smallvec![StmtKind::Empty],
StmtKind::MacCall(mut mac) => { StmtKind::MacCall(mut mac) => {
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut(); let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
vis.visit_mac_call(mac_);
visit_attrs(attrs, vis); visit_attrs(attrs, vis);
vis.visit_mac_call(mac_);
visit_lazy_tts(tokens, vis); visit_lazy_tts(tokens, vis);
smallvec![StmtKind::MacCall(mac)] smallvec![StmtKind::MacCall(mac)]
} }
@ -1657,8 +1657,8 @@ fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
match &mut visibility.kind { match &mut visibility.kind {
VisibilityKind::Public | VisibilityKind::Inherited => {} VisibilityKind::Public | VisibilityKind::Inherited => {}
VisibilityKind::Restricted { path, id, shorthand: _ } => { VisibilityKind::Restricted { path, id, shorthand: _ } => {
vis.visit_path(path);
vis.visit_id(id); vis.visit_id(id);
vis.visit_path(path);
} }
} }
vis.visit_span(&mut visibility.span); vis.visit_span(&mut visibility.span);

View File

@ -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 { 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_attribute, &krate.attrs);
walk_list!(visitor, visit_item, &krate.items);
V::Result::output() V::Result::output()
} }
@ -462,25 +462,25 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -
where where
V: Visitor<'a>, V: Visitor<'a>,
{ {
walk_list!(visitor, visit_attribute, &variant.attrs);
try_visit!(visitor.visit_ident(variant.ident)); try_visit!(visitor.visit_ident(variant.ident));
try_visit!(visitor.visit_vis(&variant.vis)); try_visit!(visitor.visit_vis(&variant.vis));
try_visit!(visitor.visit_variant_data(&variant.data)); try_visit!(visitor.visit_variant_data(&variant.data));
visit_opt!(visitor, visit_variant_discr, &variant.disr_expr); visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
walk_list!(visitor, visit_attribute, &variant.attrs);
V::Result::output() V::Result::output()
} }
pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result { 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_expr(&f.expr));
try_visit!(visitor.visit_ident(f.ident)); try_visit!(visitor.visit_ident(f.ident));
walk_list!(visitor, visit_attribute, &f.attrs);
V::Result::output() V::Result::output()
} }
pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result { 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_ident(fp.ident));
try_visit!(visitor.visit_pat(&fp.pat)); try_visit!(visitor.visit_pat(&fp.pat));
walk_list!(visitor, visit_attribute, &fp.attrs);
V::Result::output() V::Result::output()
} }
@ -722,8 +722,8 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
visitor: &mut V, visitor: &mut V,
param: &'a GenericParam, param: &'a GenericParam,
) -> V::Result { ) -> V::Result {
try_visit!(visitor.visit_ident(param.ident));
walk_list!(visitor, visit_attribute, &param.attrs); walk_list!(visitor, visit_attribute, &param.attrs);
try_visit!(visitor.visit_ident(param.ident));
walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound); walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
match &param.kind { match &param.kind {
GenericParamKind::Lifetime => (), GenericParamKind::Lifetime => (),
@ -882,10 +882,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
ctxt: AssocCtxt, ctxt: AssocCtxt,
) -> V::Result { ) -> V::Result {
let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; 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_vis(vis));
try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ident(ident));
try_visit!(kind.walk(item, ctxt, visitor)); try_visit!(kind.walk(item, ctxt, visitor));
walk_list!(visitor, visit_attribute, attrs);
V::Result::output() 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 { 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)); try_visit!(visitor.visit_vis(&field.vis));
visit_opt!(visitor, visit_ident, field.ident); visit_opt!(visitor, visit_ident, field.ident);
try_visit!(visitor.visit_ty(&field.ty)); try_visit!(visitor.visit_ty(&field.ty));
walk_list!(visitor, visit_attribute, &field.attrs);
V::Result::output() 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::Empty => {}
StmtKind::MacCall(mac) => { StmtKind::MacCall(mac) => {
let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
try_visit!(visitor.visit_mac_call(mac));
walk_list!(visitor, visit_attribute, attrs); walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_mac_call(mac));
} }
} }
V::Result::output() 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 { 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)); try_visit!(visitor.visit_pat(&arm.pat));
visit_opt!(visitor, visit_expr, &arm.guard); visit_opt!(visitor, visit_expr, &arm.guard);
visit_opt!(visitor, visit_expr, &arm.body); visit_opt!(visitor, visit_expr, &arm.body);
walk_list!(visitor, visit_attribute, &arm.attrs);
V::Result::output() V::Result::output()
} }

View File

@ -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 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 .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}` 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_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`

View File

@ -434,5 +434,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
lints::InnerAttributeUnstable::CustomInnerAttribute lints::InnerAttributeUnstable::CustomInnerAttribute
} }
.decorate_lint(diag), .decorate_lint(diag),
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
}
} }
} }

View File

@ -2911,3 +2911,10 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
#[suggestion_part(code = ")")] #[suggestion_part(code = ")")]
pub right: Span, pub right: Span,
} }
#[derive(LintDiagnostic)]
#[diag(lint_out_of_scope_macro_calls)]
#[help]
pub struct OutOfScopeMacroCalls {
pub path: String,
}

View File

@ -4945,3 +4945,42 @@ declare_lint! {
reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>", reference: "issue #123757 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/124535>",
};
}

View File

@ -744,6 +744,9 @@ pub enum BuiltinLintDiag {
InnerAttributeUnstable { InnerAttributeUnstable {
is_macro: bool, is_macro: bool,
}, },
OutOfScopeMacroCalls {
path: String,
},
} }
/// Lints that are buffered up early on in the `Session` before the /// Lints that are buffered up early on in the `Session` before the

View File

@ -14,7 +14,7 @@ use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, Modul
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError};
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError}; 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::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
use rustc_attr as attr; 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; let orig_macro_rules_scope = self.parent_scope.macro_rules;
self.build_reduced_graph_for_item(item); 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 { match item.kind {
ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => { ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
self.parent_scope.macro_rules self.parent_scope.macro_rules
@ -1514,7 +1524,10 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
if krate.is_placeholder { if krate.is_placeholder {
self.visit_invoc_in_module(krate.id); self.visit_invoc_in_module(krate.id);
} else { } 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); self.contains_macro_use(&krate.attrs);
} }
} }

View File

@ -5,7 +5,7 @@ use crate::errors::CannotDetermineMacroResolution;
use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope}; use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope};
use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive}; use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive};
use crate::Namespace::*; 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::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
use rustc_ast::expand::StrippedCfgItem; 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::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand};
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::compile_declarative_macro; 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::{self, DefKind, Namespace, NonMacroAttrKind};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::middle::stability; use rustc_middle::middle::stability;
use rustc_middle::ty::RegisteredTools; use rustc_middle::ty::RegisteredTools;
use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_middle::ty::{TyCtxt, Visibility};
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_session::lint::builtin::{
use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, SOFT_UNSTABLE,
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACROS, UNUSED_MACRO_RULES,
};
use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::edit_distance::edit_distance; use rustc_span::edit_distance::edit_distance;
@ -289,6 +292,16 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
let parent_scope = &ParentScope { derives, ..parent_scope }; let parent_scope = &ParentScope { derives, ..parent_scope };
let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion(); let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
let node_id = invoc.expansion_data.lint_node_id; 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( let (ext, res) = self.smart_resolve_macro_path(
path, path,
kind, kind,
@ -299,6 +312,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
force, force,
soft_custom_inner_attributes_gate(path, invoc), soft_custom_inner_attributes_gate(path, invoc),
deleg_impl, deleg_impl,
looks_like_invoc_in_mod_inert_attr,
)?; )?;
let span = invoc.span(); let span = invoc.span();
@ -521,6 +535,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
force: bool, force: bool,
soft_custom_inner_attributes_gate: bool, soft_custom_inner_attributes_gate: bool,
deleg_impl: Option<LocalDefId>, deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<LocalDefId>,
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> { ) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
let (ext, res) = match self.resolve_macro_or_delegation_path( let (ext, res) = match self.resolve_macro_or_delegation_path(
path, path,
@ -529,6 +544,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
true, true,
force, force,
deleg_impl, deleg_impl,
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
) { ) {
Ok((Some(ext), res)) => (ext, res), Ok((Some(ext), res)) => (ext, res),
Ok((None, res)) => (self.dummy_ext(kind), res), Ok((None, res)) => (self.dummy_ext(kind), res),
@ -683,20 +699,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
trace: bool, trace: bool,
force: bool, force: bool,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> { ) -> Result<(Option<Lrc<SyntaxExtension>>, 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( fn resolve_macro_or_delegation_path(
&mut self, &mut self,
path: &ast::Path, ast_path: &ast::Path,
kind: Option<MacroKind>, kind: Option<MacroKind>,
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
trace: bool, trace: bool,
force: bool, force: bool,
deleg_impl: Option<LocalDefId>, deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> { ) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
let path_span = path.span; let path_span = ast_path.span;
let mut path = Segment::from_path(path); let mut path = Segment::from_path(ast_path);
// Possibly apply the macro helper hack // Possibly apply the macro helper hack
if deleg_impl.is_none() if deleg_impl.is_none()
@ -762,6 +779,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let res = binding.map(|binding| binding.res()); let res = binding.map(|binding| binding.res());
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span); 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 res
}; };
@ -1014,6 +1037,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<NameBinding<'a>>,
) {
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) { 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 // Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`. // performed on `Resolver::builtin_attrs`.

View File

@ -1,11 +1,17 @@
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`
|
= 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` error: `feature = "cargo-clippy"` was replaced by `clippy`
--> tests/ui/cfg_attr_cargo_clippy.rs:5:12 --> tests/ui/cfg_attr_cargo_clippy.rs:5:12
| |
LL | #[cfg_attr(feature = "cargo-clippy", derive(Debug))] LL | #[cfg_attr(feature = "cargo-clippy", derive(Debug))]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` | ^^^^^^^^^^^^^^^^^^^^^^^^ 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` error: `feature = "cargo-clippy"` was replaced by `clippy`
--> tests/ui/cfg_attr_cargo_clippy.rs:6:16 --> 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"))] LL | #[cfg(all(feature = "cargo-clippy"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `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 error: aborting due to 7 previous errors

View File

@ -1,35 +1,11 @@
error: using tabs in doc comments is not recommended
--> tests/ui/tabs_in_doc_comments.rs:10:9
|
LL | /// - First String:
| ^^^^ 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
|
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:14:9
|
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:15:9
|
LL | /// - needs to be inside here
| ^^^^^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended 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:6:5
| |
LL | /// - first one LL | /// - first one
| ^^^^ help: consider using four spaces per tab | ^^^^ 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 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:6:13
@ -49,5 +25,29 @@ error: using tabs in doc comments is not recommended
LL | /// - second one LL | /// - second one
| ^^^^ help: consider using four spaces per tab | ^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
--> tests/ui/tabs_in_doc_comments.rs:10:9
|
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:11:9
|
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:14:9
|
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:15:9
|
LL | /// - needs to be inside here
| ^^^^^^^^ help: consider using four spaces per tab
error: aborting due to 8 previous errors error: aborting due to 8 previous errors

View File

@ -1,39 +1,11 @@
error: no need to put clippy lints behind a `clippy` cfg
--> 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)]`
|
= 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
|
LL | #[cfg_attr(clippy, deny(dead_code, 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
|
LL | #[cfg_attr(clippy, deny(dead_code, 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
|
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 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:4:1
| |
LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![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 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:6:37
@ -57,6 +29,34 @@ error: no need to put clippy lints behind a `clippy` cfg
LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![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:13:1
|
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:15:36
|
LL | #[cfg_attr(clippy, deny(dead_code, 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
|
LL | #[cfg_attr(clippy, deny(dead_code, 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
|
LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]`
error: duplicated attribute error: duplicated attribute
--> tests/ui/unnecessary_clippy_cfg.rs:8:26 --> tests/ui/unnecessary_clippy_cfg.rs:8:26
| |

View File

@ -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() {}

View File

@ -1,6 +1,8 @@
#![doc = in_root!()] // FIXME, this is a bug #![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!()] //~ ERROR cannot find macro `in_mod` in this scope
#![doc = in_mod_escape!()] // FIXME, this is a bug #![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_block!()] //~ ERROR cannot find macro `in_block` in this scope
#[doc = in_root!()] //~ ERROR cannot find macro `in_root` 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 { () => { "" } } 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 { mod macros_stay {
#![doc = in_mod!()] // FIXME, this is a bug #![doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope
//~| WARN this was previously accepted by the compiler
macro_rules! in_mod { () => { "" } } macro_rules! in_mod { () => { "" } }
@ -28,8 +33,11 @@ mod macros_stay {
} }
#[macro_use] #[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 { mod macros_escape {
#![doc = in_mod_escape!()] // FIXME, this is a bug #![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 { () => { "" } } 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() { 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 { () => { "" } } macro_rules! in_block { () => { "" } }

View File

@ -1,5 +1,5 @@
error: cannot find macro `in_mod` in this scope 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!()] LL | #![doc = in_mod!()]
| ^^^^^^ | ^^^^^^
@ -7,7 +7,7 @@ LL | #![doc = in_mod!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope 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!()] LL | #![doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
@ -15,7 +15,7 @@ LL | #![doc = in_block!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_root` in this scope 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!()] LL | #[doc = in_root!()]
| ^^^^^^^ | ^^^^^^^
@ -23,7 +23,7 @@ LL | #[doc = in_root!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod` in this scope 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!()] LL | #[doc = in_mod!()]
| ^^^^^^ | ^^^^^^
@ -31,7 +31,7 @@ LL | #[doc = in_mod!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod_escape` in this scope 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!()] LL | #[doc = in_mod_escape!()]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
@ -39,7 +39,7 @@ LL | #[doc = in_mod_escape!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope 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!()] LL | #[doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
@ -47,7 +47,7 @@ LL | #[doc = in_block!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_root` in this scope 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!()] LL | #![doc = in_root!()]
| ^^^^^^^ | ^^^^^^^
@ -55,7 +55,7 @@ LL | #![doc = in_root!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod` in this scope 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!()] LL | #![doc = in_mod!()]
| ^^^^^^ | ^^^^^^
@ -63,7 +63,7 @@ LL | #![doc = in_mod!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod_escape` in this scope 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!()] LL | #![doc = in_mod_escape!()]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
@ -71,7 +71,7 @@ LL | #![doc = in_mod_escape!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope 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!()] LL | #![doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
@ -79,7 +79,15 @@ LL | #![doc = in_block!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope error: cannot find macro `in_block` in this scope
--> $DIR/key-value-expansion-scope.rs:43:14 --> $DIR/key-value-expansion-scope.rs:50:9
|
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:52:14
| |
LL | #![doc = in_block!()] LL | #![doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
@ -87,7 +95,7 @@ LL | #![doc = in_block!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod` in this scope 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!()] LL | #[doc = in_mod!()]
| ^^^^^^ | ^^^^^^
@ -95,7 +103,7 @@ LL | #[doc = in_mod!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope 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!()] LL | #[doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
@ -103,7 +111,7 @@ LL | #[doc = in_block!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_mod` in this scope 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!()] LL | #![doc = in_mod!()]
| ^^^^^^ | ^^^^^^
@ -111,12 +119,73 @@ LL | #![doc = in_mod!()]
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: cannot find macro `in_block` in this scope 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!()] LL | #![doc = in_block!()]
| ^^^^^^^^ | ^^^^^^^^
| |
= help: have you added the `#[macro_use]` on the module/import? = help: have you added the `#[macro_use]` on the module/import?
error: aborting due to 15 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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/124535>
= help: import `macro_rules` with `use` to make it callable above its definition
error: aborting due to 16 previous errors; 6 warnings emitted

View File

@ -1,3 +1,23 @@
error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:2:1
|
LL | #![optimize(speed)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/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
|
LL | #[optimize(size)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/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 error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:7:1 --> $DIR/feature-gate-optimize_attribute.rs:7:1
| |
@ -28,26 +48,6 @@ LL | #[optimize(banana)]
= help: add `#![feature(optimize_attribute)]` to the crate attributes to enable = 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 = 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
|
LL | #[optimize(size)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/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
|
LL | #![optimize(speed)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/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[E0722]: invalid argument error[E0722]: invalid argument
--> $DIR/feature-gate-optimize_attribute.rs:13:12 --> $DIR/feature-gate-optimize_attribute.rs:13:12
| |

View File

@ -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 error[E0734]: stability attributes may not be used outside of the standard library
--> $DIR/feature-gate-staged_api.rs:1:1 --> $DIR/feature-gate-staged_api.rs:1:1
| |
LL | #![stable(feature = "a", since = "3.3.3")] 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 error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0734`. For more information about this error, try `rustc --explain E0734`.

View File

@ -42,6 +42,20 @@ warning: unknown lint: `x5100`
LL | #![deny(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` warning: unknown lint: `x5400`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8
| |
@ -186,20 +200,6 @@ warning: unknown lint: `x5100`
LL | #[deny(x5100)] impl S { } 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 warning: `#[macro_export]` only has an effect on macro definitions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1
| |

View File

@ -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 error[E0734]: stability attributes may not be used outside of the standard library
--> $DIR/issue-43106-gating-of-stable.rs:14:9 --> $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()] 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 error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0734`. For more information about this error, try `rustc --explain E0734`.

View File

@ -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 error[E0734]: stability attributes may not be used outside of the standard library
--> $DIR/issue-43106-gating-of-unstable.rs:14:9 --> $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()] 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 error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0734`. For more information about this error, try `rustc --explain E0734`.

View File

@ -1,15 +1,15 @@
error[E0734]: stability attributes may not be used outside of the standard library
--> $DIR/issue-106589.rs:6:1
|
LL | #[unstable(feature = "foo", issue = "none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0734]: stability attributes may not be used outside of the standard library error[E0734]: stability attributes may not be used outside of the standard library
--> $DIR/issue-106589.rs:3:1 --> $DIR/issue-106589.rs:3:1
| |
LL | #![stable(feature = "foo", since = "1.0.0")] 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:6:1
|
LL | #[unstable(feature = "foo", issue = "none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0734`. For more information about this error, try `rustc --explain E0734`.