Skip to content

Port #[macro_export] to the new attribute parsing infrastructure #143857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ pub enum AttributeKind {
/// Represents `#[loop_match]`.
LoopMatch(Span),

/// Represents [`#[macro_export}`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path).
MacroExport { span: Span, local_inner_macros: bool },

/// Represents `#[rustc_macro_transparency]`.
MacroTransparency(Transparency),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ impl AttributeKind {
LinkName { .. } => Yes,
LinkSection { .. } => No,
LoopMatch(..) => No,
MacroExport { .. } => Yes,
MacroTransparency(..) => Yes,
Marker(..) => No,
MayDangle(..) => No,
Expand Down
45 changes: 45 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_attr_data_structures::AttributeKind::MacroExport;
use rustc_attr_data_structures::lints::AttributeLintKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;

pub(crate) struct MacroExportParser;

impl<S: Stage> SingleAttributeParser<S> for crate::attributes::macro_attrs::MacroExportParser {
const PATH: &[Symbol] = &[sym::macro_export];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(Word, List: "local_inner_macros");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let local_inner_macros = match args {
ArgParser::NoArgs => false,
ArgParser::List(list) => {
let Some(l) = list.single() else {
cx.expected_single_argument(list.span);
return None;
};
match l.meta_item().and_then(|i| i.path().word_sym()) {
Some(sym::local_inner_macros) => true,
_ => {
cx.expected_specific_argument(l.span(), vec!["local_inner_macros"]);
return None;
}
}
}
ArgParser::NameValue(_) => {
let suggestions =
<Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "macro_export");
let span = cx.attr_span;
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
return None;
}
};
Some(MacroExport { span: cx.attr_span, local_inner_macros })
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,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;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::attributes::link_attrs::{
};
use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::macro_attrs::MacroExportParser;
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
Expand Down Expand Up @@ -142,6 +143,7 @@ attribute_parsers!(
Single<InlineParser>,
Single<LinkNameParser>,
Single<LinkSectionParser>,
Single<MacroExportParser>,
Single<MustUseParser>,
Single<OptimizeParser>,
Single<PathAttributeParser>,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,9 +892,9 @@ impl SyntaxExtension {
let allow_internal_unsafe =
ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some();

let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
.and_then(|macro_export| macro_export.meta_item_list())
.is_some_and(|l| ast::attr::list_contains_name(&l, sym::local_inner_macros));
let local_inner_macros =
*find_attr!(attrs, AttributeKind::MacroExport {local_inner_macros: l, ..} => l)
.unwrap_or(&false);
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);

Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_lint/src/non_local_def.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_errors::MultiSpan;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind};
use rustc_middle::ty::TyCtxt;
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::{ExpnKind, MacroKind, Span, kw, sym};
use rustc_span::{ExpnKind, MacroKind, Span, kw};

use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
Expand Down Expand Up @@ -241,7 +242,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
)
}
ItemKind::Macro(_, _macro, MacroKind::Bang)
if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
if find_attr!(
cx.tcx.get_all_attrs(item.owner_id.def_id),
AttributeKind::MacroExport { .. }
) =>
{
cx.emit_span_lint(
NON_LOCAL_DEFINITIONS,
Expand Down
31 changes: 0 additions & 31 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ declare_lint_pass! {
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
INLINE_NO_SANITIZE,
INVALID_DOC_ATTRIBUTES,
INVALID_MACRO_EXPORT_ARGUMENTS,
INVALID_TYPE_PARAM_DEFAULT,
IRREFUTABLE_LET_PATTERNS,
LARGE_ASSIGNMENTS,
Expand Down Expand Up @@ -4161,36 +4160,6 @@ declare_lint! {
report_in_external_macro
}

declare_lint! {
/// The `invalid_macro_export_arguments` lint detects cases where `#[macro_export]` is being used with invalid arguments.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(invalid_macro_export_arguments)]
///
/// #[macro_export(invalid_parameter)]
/// macro_rules! myMacro {
/// () => {
/// // [...]
/// }
/// }
///
/// #[macro_export(too, many, items)]
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The only valid argument is `#[macro_export(local_inner_macros)]` or no argument (`#[macro_export]`).
/// You can't have multiple arguments in a `#[macro_export(..)]`, or mention arguments other than `local_inner_macros`.
///
pub INVALID_MACRO_EXPORT_ARGUMENTS,
Warn,
"\"invalid_parameter\" isn't a valid argument for `#[macro_export]`",
}

declare_lint! {
/// The `private_interfaces` lint detects types in a primary interface of an item,
/// that are more private than the item itself. Primary interface of an item is all
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_parse/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ pub fn check_builtin_meta_item(
| sym::cold
| sym::target_feature
| sym::rustc_allow_const_fn_unstable
| sym::macro_export
| sym::naked
| sym::no_mangle
| sym::non_exhaustive
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,6 @@ passes_invalid_attr_at_crate_level =
passes_invalid_attr_at_crate_level_item =
the inner attribute doesn't annotate this {$kind}

passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument

passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments

passes_lang_item_fn = {$name ->
[panic_impl] `#[panic_handler]`
*[other] `{$name}` lang item
Expand Down
39 changes: 13 additions & 26 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ use rustc_middle::{bug, span_bug};
use rustc_session::config::CrateType;
use rustc_session::lint;
use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
};
use rustc_session::parse::feature_err;
use rustc_span::edition::Edition;
Expand Down Expand Up @@ -242,6 +242,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::MacroTransparency(_)
| AttributeKind::Dummy,
) => { /* do nothing */ }
Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => {
self.check_macro_export(hir_id, *span, target)
}
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
}
Expand Down Expand Up @@ -331,7 +334,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
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, ..] => {
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn)
}
Expand Down Expand Up @@ -2295,32 +2297,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) {
if target != Target::MacroDef {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
attr_span,
errors::MacroExport::Normal,
);
} else if let Some(meta_item_list) = attr.meta_item_list()
&& !meta_item_list.is_empty()
{
if meta_item_list.len() > 1 {
self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
attr.span(),
errors::MacroExport::TooManyItems,
);
} else if !meta_item_list[0].has_name(sym::local_inner_macros) {
self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
meta_item_list[0].span(),
errors::MacroExport::InvalidArgument,
);
}
} else {
// special case when `#[macro_export]` is applied to a macro 2.0
let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro();
Expand All @@ -2330,7 +2314,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
attr_span,
errors::MacroExport::OnDeclMacro,
);
}
Expand Down Expand Up @@ -2684,7 +2668,9 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
// In the long run, the checks should be harmonized.
if let ItemKind::Macro(_, macro_def, _) = item.kind {
let def_id = item.owner_id.to_def_id();
if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
if macro_def.macro_rules
&& !find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. })
{
check_non_exported_macro_for_invalid_attrs(self.tcx, item);
}
}
Expand Down Expand Up @@ -2814,7 +2800,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
// which were unsuccessfully resolved due to cannot determine
// resolution for the attribute macro error.
const ATTRS_TO_CHECK: &[Symbol] = &[
sym::macro_export,
sym::automatically_derived,
sym::rustc_main,
sym::derive,
Expand All @@ -2838,6 +2823,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
(*first_attr_span, sym::repr)
} else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr {
(*span, sym::path)
} else if let Attribute::Parsed(AttributeKind::MacroExport { span, .. }) = attr {
(*span, sym::macro_export)
} else {
continue;
};
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,12 +769,6 @@ pub(crate) enum MacroExport {
#[diag(passes_macro_export_on_decl_macro)]
#[note]
OnDeclMacro,

#[diag(passes_invalid_macro_export_arguments)]
InvalidArgument,

#[diag(passes_invalid_macro_export_arguments_too_many_items)]
TooManyItems,
}

#[derive(Subdiagnostic)]
Expand Down
22 changes: 12 additions & 10 deletions src/librustdoc/html/render/search_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, VecDeque};

use encode::{bitmap_to_string, write_vlqhex_to_string};
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
Expand Down Expand Up @@ -408,16 +409,17 @@ pub(crate) fn build_index(
if fqp.last() != Some(&item.name) {
return None;
}
let path =
if item.ty == ItemType::Macro && tcx.has_attr(defid, sym::macro_export) {
// `#[macro_export]` always exports to the crate root.
tcx.crate_name(defid.krate).to_string()
} else {
if fqp.len() < 2 {
return None;
}
join_with_double_colon(&fqp[..fqp.len() - 1])
};
let path = if item.ty == ItemType::Macro
&& find_attr!(tcx.get_all_attrs(defid), AttributeKind::MacroExport { .. })
{
// `#[macro_export]` always exports to the crate root.
tcx.crate_name(defid.krate).to_string()
} else {
if fqp.len() < 2 {
return None;
}
join_with_double_colon(&fqp[..fqp.len() - 1])
};
if path == item.path {
return None;
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/passes/strip_hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

use std::mem;

use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use tracing::debug;

use crate::clean::utils::inherits_doc_hidden;
Expand Down Expand Up @@ -114,7 +114,7 @@ impl DocFolder for Stripper<'_, '_> {
// If the macro has the `#[macro_export]` attribute, it means it's accessible at the
// crate level so it should be handled differently.
clean::MacroItem(..) => {
i.attrs.other_attrs.iter().any(|attr| attr.has_name(sym::macro_export))
find_attr!(&i.attrs.other_attrs, AttributeKind::MacroExport { .. })
}
_ => false,
};
Expand Down
8 changes: 5 additions & 3 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use std::mem;

use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
Expand Down Expand Up @@ -167,7 +168,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
if !child.reexport_chain.is_empty()
&& let Res::Def(DefKind::Macro(_), def_id) = child.res
&& let Some(local_def_id) = def_id.as_local()
&& self.cx.tcx.has_attr(def_id, sym::macro_export)
&& find_attr!(self.cx.tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. })
&& inserted.insert(def_id)
{
let item = self.cx.tcx.hir_expect_item(local_def_id);
Expand Down Expand Up @@ -407,7 +408,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|| match item.kind {
hir::ItemKind::Impl(..) => true,
hir::ItemKind::Macro(_, _, MacroKind::Bang) => {
self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
find_attr!(self.cx.tcx.get_all_attrs(item.owner_id.def_id), AttributeKind::MacroExport{..})
}
_ => false,
}
Expand Down Expand Up @@ -525,7 +526,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {

let def_id = item.owner_id.to_def_id();
let is_macro_2_0 = !macro_def.macro_rules;
let nonexported = !tcx.has_attr(def_id, sym::macro_export);
let nonexported =
!find_attr!(tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. });

if is_macro_2_0 || nonexported || self.inlining {
self.add_to_current_mod(item, renamed, import_id);
Expand Down
Loading
Loading