Auto merge of #143843 - JonathanBrouwer:macro-use-parser, r=oli-obk

Ports `#[macro_use]` and `#[macro_escape]` to the new attribute parsing infrastructure

Ports `#[macro_use]` and `#[macro_escape]` to the new attribute parsing infrastructure for https://github.com/rust-lang/rust/issues/131229#issuecomment-2971351163

r? `@jdonszelmann` `@oli-obk`
This commit is contained in:
bors 2025-07-23 13:57:12 +00:00
commit 4ff3fa01cb
53 changed files with 480 additions and 150 deletions

View file

@ -157,6 +157,19 @@ pub enum UsedBy {
Linker,
}
#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic, PrintAttribute)]
pub enum MacroUseArgs {
UseAll,
UseSpecific(ThinVec<Ident>),
}
impl Default for MacroUseArgs {
fn default() -> Self {
Self::UseSpecific(ThinVec::new())
}
}
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
pub struct StrippedCfgItem<ModId = DefId> {
pub parent_module: ModId,
@ -351,9 +364,15 @@ pub enum AttributeKind {
/// Represents `#[loop_match]`.
LoopMatch(Span),
/// Represents `#[macro_escape]`.
MacroEscape(Span),
/// Represents `#[rustc_macro_transparency]`.
MacroTransparency(Transparency),
/// Represents `#[macro_use]`.
MacroUse { span: Span, arguments: MacroUseArgs },
/// Represents `#[marker]`.
Marker(Span),

View file

@ -45,7 +45,9 @@ impl AttributeKind {
LinkOrdinal { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc
LoopMatch(..) => No,
MacroEscape(..) => No,
MacroTransparency(..) => Yes,
MacroUse { .. } => No,
Marker(..) => No,
MayDangle(..) => No,
MustUse { .. } => Yes,

View file

@ -24,7 +24,7 @@ use rustc_ast::token::CommentKind;
use rustc_ast::{AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
pub use stability::*;
use thin_vec::ThinVec;
pub use version::*;
@ -172,7 +172,7 @@ macro_rules! print_tup {
print_tup!(A B C D E F G H);
print_skip!(Span, (), ErrorGuaranteed);
print_disp!(u16, bool, NonZero<u32>);
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
/// Finds attributes in sequences of attributes by pattern matching.
///

View file

@ -0,0 +1,115 @@
use rustc_attr_data_structures::{AttributeKind, MacroUseArgs};
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate};
use crate::context::{AcceptContext, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
pub(crate) struct MacroEscapeParser;
impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
const PATH: &[Symbol] = &[sym::macro_escape];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::MacroEscape;
}
/// `#[macro_use]` attributes can either:
/// - Use all macros from a crate, if provided without arguments
/// - Use specific macros from a crate, if provided with arguments `#[macro_use(macro1, macro2)]`
/// A warning should be provided if an use all is combined with specific uses, or if multiple use-alls are used.
#[derive(Default)]
pub(crate) struct MacroUseParser {
state: MacroUseArgs,
/// Spans of all `#[macro_use]` arguments with arguments, used for linting
uses_attr_spans: ThinVec<Span>,
/// If `state` is `UseSpecific`, stores the span of the first `#[macro_use]` argument, used as the span for this attribute
/// If `state` is `UseAll`, stores the span of the first `#[macro_use]` arguments without arguments
first_span: Option<Span>,
}
const MACRO_USE_TEMPLATE: AttributeTemplate = template!(Word, List: "name1, name2, ...");
impl<S: Stage> AttributeParser<S> for MacroUseParser {
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
&[sym::macro_use],
MACRO_USE_TEMPLATE,
|group: &mut Self, cx: &mut AcceptContext<'_, '_, S>, args| {
let span = cx.attr_span;
group.first_span.get_or_insert(span);
match args {
ArgParser::NoArgs => {
match group.state {
MacroUseArgs::UseAll => {
let first_span = group.first_span.expect(
"State is UseAll is some so this is not the first attribute",
);
// Since there is a `#[macro_use]` import already, give a warning
cx.warn_unused_duplicate(first_span, span);
}
MacroUseArgs::UseSpecific(_) => {
group.state = MacroUseArgs::UseAll;
group.first_span = Some(span);
// If there is a `#[macro_use]` attribute, warn on all `#[macro_use(...)]` attributes since everything is already imported
for specific_use in group.uses_attr_spans.drain(..) {
cx.warn_unused_duplicate(span, specific_use);
}
}
}
}
ArgParser::List(list) => {
if list.is_empty() {
cx.warn_empty_attribute(list.span);
return;
}
match &mut group.state {
MacroUseArgs::UseAll => {
let first_span = group.first_span.expect(
"State is UseAll is some so this is not the first attribute",
);
cx.warn_unused_duplicate(first_span, span);
}
MacroUseArgs::UseSpecific(arguments) => {
// Store here so if we encounter a `UseAll` later we can still lint this attribute
group.uses_attr_spans.push(cx.attr_span);
for item in list.mixed() {
let Some(item) = item.meta_item() else {
cx.expected_identifier(item.span());
continue;
};
if let Err(err_span) = item.args().no_args() {
cx.expected_no_args(err_span);
continue;
}
let Some(item) = item.path().word() else {
cx.expected_identifier(item.span());
continue;
};
arguments.push(item);
}
}
}
}
ArgParser::NameValue(_) => {
let suggestions = MACRO_USE_TEMPLATE.suggestions(false, sym::macro_use);
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
),
span,
});
}
}
},
)];
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
}
}

View file

@ -36,6 +36,7 @@ pub(crate) mod inline;
pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod macro_attrs;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod non_exhaustive;

View file

@ -34,7 +34,7 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
ArgParser::List(_) => {
let suggestions =
<Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
cx.emit_err(session_diagnostics::MustUseIllFormedAttributeInput {
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),

View file

@ -33,6 +33,7 @@ use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
@ -126,6 +127,7 @@ attribute_parsers!(
BodyStabilityParser,
ConfusablesParser,
ConstStabilityParser,
MacroUseParser,
NakedParser,
StabilityParser,
UsedParser,
@ -174,6 +176,7 @@ attribute_parsers!(
Single<WithoutArgs<FfiPureParser>>,
Single<WithoutArgs<FundamentalParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MacroEscapeParser>>,
Single<WithoutArgs<MarkerParser>>,
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
@ -386,6 +389,17 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
})
}
/// emit an error that a `name` was expected here
pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
reason: AttributeParseErrorReason::ExpectedIdentifier,
})
}
/// emit an error that a `name = value` pair was expected at this span. The symbol can be given for
/// a nicer error message talking about the specific name that was found lacking a value.
pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {

View file

@ -438,7 +438,7 @@ pub(crate) struct IllFormedAttributeInput {
#[derive(Diagnostic)]
#[diag(attr_parsing_ill_formed_attribute_input)]
pub(crate) struct MustUseIllFormedAttributeInput {
pub(crate) struct IllFormedAttributeInputLint {
#[primary_span]
pub span: Span,
pub num_suggestions: usize,
@ -549,6 +549,7 @@ pub(crate) enum AttributeParseErrorReason {
/// Should we tell the user to write a list when they didn't?
list: bool,
},
ExpectedIdentifier,
}
pub(crate) struct AttributeParseError {
@ -600,11 +601,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
diag.code(E0538);
}
AttributeParseErrorReason::UnexpectedLiteral => {
diag.span_label(self.span, format!("didn't expect a literal here"));
diag.span_label(self.span, "didn't expect a literal here");
diag.code(E0565);
}
AttributeParseErrorReason::ExpectedNoArgs => {
diag.span_label(self.span, format!("didn't expect any arguments here"));
diag.span_label(self.span, "didn't expect any arguments here");
diag.code(E0565);
}
AttributeParseErrorReason::ExpectedNameValue(None) => {
@ -684,6 +685,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
}
}
}
AttributeParseErrorReason::ExpectedIdentifier => {
diag.span_label(self.span, "expected a valid identifier here");
}
}
let suggestions = self.template.suggestions(false, &name);

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
Macro import declaration was malformed.
Erroneous code examples:
```compile_fail,E0466
```compile_fail
#[macro_use(a_macro(another_macro))] // error: invalid import declaration
extern crate core as some_crate;

View file

@ -1302,6 +1302,7 @@ impl AttributeExt for Attribute {
// FIXME: should not be needed anymore when all attrs are parsed
Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => *span,
Attribute::Parsed(AttributeKind::MayDangle(span)) => *span,
Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span,
Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,

View file

@ -303,6 +303,8 @@ pub fn check_builtin_meta_item(
| sym::cold
| sym::target_feature
| sym::rustc_allow_const_fn_unstable
| sym::macro_use
| sym::macro_escape
| sym::naked
| sym::no_mangle
| sym::non_exhaustive

View file

@ -227,6 +227,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => {
self.check_link_section(hir_id, *attr_span, span, target)
}
Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => {
self.check_macro_use(hir_id, sym::macro_use, *span, target)
}
Attribute::Parsed(AttributeKind::MacroEscape(span)) => {
self.check_macro_use(hir_id, sym::macro_escape, *span, target)
}
Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
self.check_naked(hir_id, *attr_span, span, target)
}
@ -362,9 +368,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target),
[sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target),
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
self.check_macro_use(hir_id, attr, target)
}
[sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod),
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
[sym::should_panic, ..] => {
@ -2411,17 +2414,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
let Some(name) = attr.name() else {
return;
};
fn check_macro_use(&self, hir_id: HirId, name: Symbol, attr_span: Span, target: Target) {
match target {
Target::ExternCrate | Target::Mod => {}
_ => {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
attr_span,
errors::MacroUse { name },
);
}
@ -2474,7 +2474,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// Warn on useless empty attributes.
// FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute`
let note = if attr.has_any_name(&[
sym::macro_use,
sym::allow,
sym::expect,
sym::warn,

View file

@ -41,8 +41,6 @@ resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
resolve_attributes_starting_with_rustc_are_reserved =
attributes starting with `rustc` are reserved for use by the `rustc` compiler
resolve_bad_macro_import = bad macro import
resolve_binding_in_never_pattern =
never patterns cannot contain variable bindings
.suggestion = use a wildcard `_` instead

View file

@ -11,11 +11,14 @@ use std::sync::Arc;
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
use rustc_ast::{
self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias,
ForeignItemKind, Impl, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias,
};
use rustc_attr_data_structures::{AttributeKind, MacroUseArgs};
use rustc_attr_parsing as attr;
use rustc_attr_parsing::AttributeParser;
use rustc_expand::base::ResolverExpand;
use rustc_expand::expand::AstFragment;
use rustc_hir::Attribute;
use rustc_hir::def::{self, *};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_index::bit_set::DenseBitSet;
@ -25,6 +28,7 @@ use rustc_middle::metadata::ModChild;
use rustc_middle::ty::{Feed, Visibility};
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
use rustc_span::{Ident, Span, Symbol, kw, sym};
use thin_vec::ThinVec;
use tracing::debug;
use crate::Namespace::{MacroNS, TypeNS, ValueNS};
@ -1019,42 +1023,31 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
/// Returns `true` if we should consider the underlying `extern crate` to be used.
fn process_macro_use_imports(&mut self, item: &Item, module: Module<'ra>) -> bool {
let mut import_all = None;
let mut single_imports = Vec::new();
for attr in &item.attrs {
if attr.has_name(sym::macro_use) {
if self.parent_scope.module.parent.is_some() {
self.r.dcx().emit_err(errors::ExternCrateLoadingMacroNotAtCrateRoot {
span: item.span,
});
}
if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
&& orig_name == kw::SelfLower
{
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
}
let ill_formed = |span| {
self.r.dcx().emit_err(errors::BadMacroImport { span });
};
match attr.meta() {
Some(meta) => match meta.kind {
MetaItemKind::Word => {
import_all = Some(meta.span);
break;
}
MetaItemKind::List(meta_item_inners) => {
for meta_item_inner in meta_item_inners {
match meta_item_inner.ident() {
Some(ident) if meta_item_inner.is_word() => {
single_imports.push(ident)
}
_ => ill_formed(meta_item_inner.span()),
}
}
}
MetaItemKind::NameValue(..) => ill_formed(meta.span),
},
None => ill_formed(attr.span),
}
let mut single_imports = ThinVec::new();
if let Some(Attribute::Parsed(AttributeKind::MacroUse { span, arguments })) =
AttributeParser::parse_limited(
self.r.tcx.sess,
&item.attrs,
sym::macro_use,
item.span,
item.id,
None,
)
{
if self.parent_scope.module.parent.is_some() {
self.r
.dcx()
.emit_err(errors::ExternCrateLoadingMacroNotAtCrateRoot { span: item.span });
}
if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
&& orig_name == kw::SelfLower
{
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span });
}
match arguments {
MacroUseArgs::UseAll => import_all = Some(span),
MacroUseArgs::UseSpecific(imports) => single_imports = imports,
}
}

View file

@ -815,13 +815,6 @@ pub(crate) struct ExternCrateLoadingMacroNotAtCrateRoot {
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_bad_macro_import, code = E0466)]
pub(crate) struct BadMacroImport {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_extern_crate_self_requires_renaming)]
pub(crate) struct ExternCrateSelfRequiresRenaming {

View file

@ -7,8 +7,9 @@ use rustc_hir::{self as hir, AmbigArg};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition;
use rustc_span::{Span, sym};
use rustc_span::{Span};
use std::collections::BTreeMap;
use rustc_attr_data_structures::{AttributeKind, find_attr};
declare_clippy_lint! {
/// ### What it does
@ -99,15 +100,14 @@ impl LateLintPass<'_> for MacroUseImports {
&& let hir::ItemKind::Use(path, _kind) = &item.kind
&& let hir_id = item.hir_id()
&& let attrs = cx.tcx.hir_attrs(hir_id)
&& let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
&& let Some(mac_attr_span) = find_attr!(attrs, AttributeKind::MacroUse {span, ..} => *span)
&& let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns
&& !id.is_local()
{
for kid in cx.tcx.module_children(id) {
if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
let span = mac_attr.span();
let def_path = cx.tcx.def_path_str(mac_id);
self.imports.push((def_path, span, hir_id));
self.imports.push((def_path, mac_attr_span, hir_id));
}
}
} else if item.span.from_expansion() {

View file

@ -6,7 +6,7 @@
#![feature(fn_delegation)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
fn b<C>(e: C) { }

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir

View file

@ -5,7 +5,7 @@
#![feature(c_variadic)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
extern "C" {

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir

View file

@ -7,7 +7,7 @@
#![allow(unused)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
struct Foo<'a> {

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ pretty-compare-only
//@ pretty-mode:hir,typed

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
// Test to print lifetimes on HIR pretty-printing.

View file

@ -6,7 +6,7 @@
#![allow(dead_code, incomplete_features)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
use std::pin::Pin;

View file

@ -0,0 +1,53 @@
#![deny(unused_attributes)]
//~^ NOTE the lint level is defined here
#[macro_use = 5]
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
extern crate std as s1;
#[macro_use(5)]
//~^ ERROR malformed `macro_use` attribute input
//~| NOTE expected a valid identifier here
extern crate std as s2;
#[macro_use(a = "b")]
//~^ ERROR malformed `macro_use` attribute input
//~| NOTE didn't expect any arguments here
extern crate std as s3;
#[macro_use(a(b))]
//~^ ERROR malformed `macro_use` attribute input
//~| NOTE didn't expect any arguments here
extern crate std as s4;
#[macro_use(a::b)]
//~^ ERROR malformed `macro_use` attribute input
//~| NOTE expected a valid identifier here
extern crate std as s5;
#[macro_use(a)]
//~^ ERROR unused attribute
#[macro_use]
//~^ NOTE attribute also specified here
extern crate std as s6;
#[macro_use]
//~^ NOTE attribute also specified here
#[macro_use(a)]
//~^ ERROR unused attribute
extern crate std as s7;
#[macro_use]
//~^ NOTE attribute also specified here
#[macro_use]
//~^ ERROR unused attribute
extern crate std as s8;
// This is fine, both are importing different names
#[macro_use(a)]
//~^ ERROR imported macro not found
#[macro_use(b)]
//~^ ERROR imported macro not found
extern crate std as s9;
fn main() {}

View file

@ -0,0 +1,131 @@
error[E0469]: imported macro not found
--> $DIR/invalid-macro-use.rs:47:13
|
LL | #[macro_use(a)]
| ^
error[E0469]: imported macro not found
--> $DIR/invalid-macro-use.rs:49:13
|
LL | #[macro_use(b)]
| ^
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
--> $DIR/invalid-macro-use.rs:4:1
|
LL | #[macro_use = 5]
| ^^^^^^^^^^^^^^^^
error[E0539]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:8:1
|
LL | #[macro_use(5)]
| ^^^^^^^^^^^^-^^
| |
| expected a valid identifier here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(5)]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(5)]
LL + #[macro_use]
|
error[E0565]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:13:1
|
LL | #[macro_use(a = "b")]
| ^^^^^^^^^^^^^^-----^^
| |
| didn't expect any arguments here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(a = "b")]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(a = "b")]
LL + #[macro_use]
|
error[E0565]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:18:1
|
LL | #[macro_use(a(b))]
| ^^^^^^^^^^^^^---^^
| |
| didn't expect any arguments here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(a(b))]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(a(b))]
LL + #[macro_use]
|
error[E0539]: malformed `macro_use` attribute input
--> $DIR/invalid-macro-use.rs:23:1
|
LL | #[macro_use(a::b)]
| ^^^^^^^^^^^^----^^
| |
| expected a valid identifier here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(a::b)]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(a::b)]
LL + #[macro_use]
|
error: unused attribute
--> $DIR/invalid-macro-use.rs:28:1
|
LL | #[macro_use(a)]
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:30:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/invalid-macro-use.rs:1:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/invalid-macro-use.rs:36:1
|
LL | #[macro_use(a)]
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:34:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
error: unused attribute
--> $DIR/invalid-macro-use.rs:42:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-macro-use.rs:40:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0469, E0539, E0565.
For more information about an error, try `rustc --explain E0469`.

View file

@ -208,7 +208,7 @@ static mut TLS: u8 = 42;
#[no_link()]
//~^ ERROR malformed
#[macro_use = 1]
//~^ ERROR malformed
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
extern crate wloop;
//~^ ERROR can't find crate for `wloop` [E0463]

View file

@ -154,21 +154,6 @@ error: malformed `no_link` attribute input
LL | #[no_link()]
| ^^^^^^^^^^^^ help: must be of the form: `#[no_link]`
error: malformed `macro_use` attribute input
--> $DIR/malformed-attrs.rs:210:1
|
LL | #[macro_use = 1]
| ^^^^^^^^^^^^^^^^
|
help: the following are the possible correct uses
|
LL - #[macro_use = 1]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use = 1]
LL + #[macro_use]
|
error: malformed `macro_export` attribute input
--> $DIR/malformed-attrs.rs:215:1
|
@ -567,6 +552,12 @@ LL | #[non_exhaustive = 1]
| | didn't expect any arguments here
| help: must be of the form: `#[non_exhaustive]`
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
--> $DIR/malformed-attrs.rs:210:1
|
LL | #[macro_use = 1]
| ^^^^^^^^^^^^^^^^
error[E0565]: malformed `type_const` attribute input
--> $DIR/malformed-attrs.rs:144:5
|

View file

@ -13,7 +13,7 @@ mod macro_escape {
//~^ ERROR arguments to `macro_use` are not allowed here
#[macro_use = "2700"] struct S;
//~^ ERROR malformed `macro_use` attribute
//~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
#[macro_use] fn f() { }

View file

@ -16,20 +16,11 @@ error: arguments to `macro_use` are not allowed here
LL | #![macro_use(my_macro)]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: malformed `macro_use` attribute input
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
--> $DIR/issue-43106-gating-of-macro_use.rs:15:5
|
LL | #[macro_use = "2700"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^
|
help: the following are the possible correct uses
|
LL - #[macro_use = "2700"] struct S;
LL + #[macro_use(name1, name2, ...)] struct S;
|
LL - #[macro_use = "2700"] struct S;
LL + #[macro_use] struct S;
|
error: aborting due to 4 previous errors

View file

@ -15,18 +15,6 @@ note: the lint level is defined here
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:37:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:36:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:55:1
|
@ -128,6 +116,18 @@ note: attribute also specified here
LL | #[macro_export]
| ^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:37:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:36:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:47:1
|

View file

@ -1,8 +1,8 @@
error: `#[macro_use]` only has an effect on `extern crate` and modules
--> $DIR/unused-attr-macro-rules.rs:7:1
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/unused-attr-macro-rules.rs:9:1
|
LL | #[macro_use]
| ^^^^^^^^^^^^
LL | #[recursion_limit="1"]
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unused-attr-macro-rules.rs:1:9
@ -10,11 +10,11 @@ note: the lint level is defined here
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/unused-attr-macro-rules.rs:9:1
error: `#[macro_use]` only has an effect on `extern crate` and modules
--> $DIR/unused-attr-macro-rules.rs:7:1
|
LL | #[recursion_limit="1"]
| ^^^^^^^^^^^^^^^^^^^^^^
LL | #[macro_use]
| ^^^^^^^^^^^^
error: `#[path]` only has an effect on modules
--> $DIR/unused-attr-macro-rules.rs:8:1

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ edition: 2015

View file

@ -1,10 +1,9 @@
warning: unused attribute
--> $DIR/macro-use-all-and-none.rs:7:1
--> $DIR/macro-use-all-and-none.rs:7:12
|
LL | #[macro_use()]
| ^^^^^^^^^^^^^^ help: remove this attribute
| ^^ help: remove this attribute
|
= note: attribute `macro_use` with an empty list has no effect
note: the lint level is defined here
--> $DIR/macro-use-all-and-none.rs:4:9
|

View file

@ -1,6 +1,6 @@
#![no_std]
#[macro_use(foo(bar))] //~ ERROR bad macro import
#[macro_use(foo(bar))] //~ ERROR malformed `macro_use` attribute input
extern crate std;
fn main() {}

View file

@ -1,9 +1,20 @@
error[E0466]: bad macro import
--> $DIR/macro-use-bad-args-1.rs:3:13
error[E0565]: malformed `macro_use` attribute input
--> $DIR/macro-use-bad-args-1.rs:3:1
|
LL | #[macro_use(foo(bar))]
| ^^^^^^^^
| ^^^^^^^^^^^^^^^-----^^
| |
| didn't expect any arguments here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(foo(bar))]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(foo(bar))]
LL + #[macro_use]
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0466`.
For more information about this error, try `rustc --explain E0565`.

View file

@ -1,6 +1,6 @@
#![no_std]
#[macro_use(foo="bar")] //~ ERROR bad macro import
#[macro_use(foo="bar")] //~ ERROR malformed `macro_use` attribute input
extern crate std;
fn main() {}

View file

@ -1,9 +1,20 @@
error[E0466]: bad macro import
--> $DIR/macro-use-bad-args-2.rs:3:13
error[E0565]: malformed `macro_use` attribute input
--> $DIR/macro-use-bad-args-2.rs:3:1
|
LL | #[macro_use(foo="bar")]
| ^^^^^^^^^
| ^^^^^^^^^^^^^^^------^^
| |
| didn't expect any arguments here
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[macro_use(foo="bar")]
LL + #[macro_use(name1, name2, ...)]
|
LL - #[macro_use(foo="bar")]
LL + #[macro_use]
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0466`.
For more information about this error, try `rustc --explain E0565`.

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
// https://github.com/rust-lang/rust/issues/82329
//@ compile-flags: -Zunpretty=hir,typed

View file

@ -5,7 +5,7 @@
#![feature(type_alias_impl_trait)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
trait Animal { }

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-fail

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

View file

@ -1,6 +1,6 @@
#[prelude_import]
use std::prelude::rust_2024::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ revisions: expanded hir
//@[expanded]compile-flags: -Zunpretty=expanded

View file

@ -30,7 +30,7 @@
#![allow(incomplete_features)]
#[prelude_import]
use std::prelude::rust_2024::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
#[prelude_import]

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes
//@ check-pass

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

View file

@ -1,6 +1,6 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass

View file

@ -10,7 +10,7 @@
#![allow(dead_code)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
#[attr = MacroUse {arguments: UseAll}]
extern crate std;
fn main() ({ } as ())