Skip to content
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
19 changes: 17 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use rustc_ast::ItemKind;
use rustc_attr_ir::{MacroUseArgs, find_attr};
use rustc_feature::AttributeStability;
use rustc_lint_defs::builtin::INVALID_MACRO_EXPORT_ARGUMENTS;
use rustc_lint_defs::builtin::{INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES};
use rustc_structures::CollapseMacroDebuginfo;

use super::prelude::*;
use crate::diagnostics::MacroOnlyAttribute;
use crate::diagnostics::{MacroExport, MacroOnlyAttribute};

pub(crate) struct MacroEscapeParser;
impl NoArgsAttributeParser for MacroEscapeParser {
Expand Down Expand Up @@ -175,8 +176,22 @@ impl SingleAttributeParser for MacroExportParser {
return None;
}
};

Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
}

fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
if cx.target != Target::MacroDef {
return;
}

let item = cx.target_item.unwrap();
if let ItemKind::MacroDef(_, macro_def) = &item.kind
&& !macro_def.macro_rules
{
cx.emit_lint(UNUSED_ATTRIBUTES, MacroExport::OnDeclMacro, attr_span);
}
}
}

pub(crate) struct CollapseDebugInfoParser;
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2063,3 +2063,10 @@ pub(crate) struct UnusedDuplicate {
)]
pub warning: bool,
}

#[derive(Diagnostic)]
pub(crate) enum MacroExport {
#[diag("`#[macro_export]` has no effect on declarative macro definitions")]
#[note("declarative macros follow the same exporting rules as regular items")]
OnDeclMacro,
}
34 changes: 18 additions & 16 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,23 +510,25 @@ impl<'sess> AttributeParser<'sess> {

// Now that all attributes have been parsed, run the deferred checks. These can
// inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`.
for (check, attr_span) in deferred_checks {
check(
&mut FinalizeCheckContext {
shared: SharedContext {
cx: self,
target_span,
target,
emit_lint: &mut emit_lint,
#[cfg(debug_assertions)]
has_lint_been_emitted: AtomicBool::new(false),
if !matches!(self.should_emit, ShouldEmit::Nothing) {
for (check, attr_span) in deferred_checks {
check(
&mut FinalizeCheckContext {
shared: SharedContext {
cx: self,
target_span,
target,
emit_lint: &mut emit_lint,
#[cfg(debug_assertions)]
has_lint_been_emitted: AtomicBool::new(false),
},
all_attrs: &attr_paths,
parsed_attrs: &attributes,
target_item,
},
all_attrs: &attr_paths,
parsed_attrs: &attributes,
target_item,
},
attr_span,
);
attr_span,
);
}
}

if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate {
Expand Down
23 changes: 1 addition & 22 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
AttributeKind::Naked(..) => self.check_naked(hir_id, target),
AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span),
AttributeKind::MacroExport { span, .. } => {
self.check_macro_export(hir_id, *span, target)
}
AttributeKind::RustcLegacyConstGenerics { attr_span, fn_indexes } => {
self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes)
}
Expand Down Expand Up @@ -275,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::LinkSection { .. } => (),
AttributeKind::LoopMatch(..) => (),
AttributeKind::MacroEscape => (),
AttributeKind::MacroExport { .. } => (),
AttributeKind::MacroUse { .. } => (),
AttributeKind::Marker => (),
AttributeKind::MoveSizeLimit { .. } => (),
Expand Down Expand Up @@ -1281,25 +1279,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) {
if target != Target::MacroDef {
return;
}

// 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();
let is_decl_macro = !macro_definition.macro_rules;

if is_decl_macro {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr_span,
diagnostics::MacroExport::OnDeclMacro,
);
}
}

fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
// Warn on useless empty attributes.
// FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute`
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,6 @@ pub(crate) struct RustcForceInlineCoro {
pub span: Span,
}

#[derive(Diagnostic)]
pub(crate) enum MacroExport {
#[diag("`#[macro_export]` has no effect on declarative macro definitions")]
#[note("declarative macros follow the same exporting rules as regular items")]
OnDeclMacro,
}

#[derive(Subdiagnostic)]
pub(crate) enum UnusedNote {
#[note("attribute `{$name}` with an empty list has no effect")]
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/attributes/macro_export_on_decl_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@
#[macro_export] //~ ERROR `#[macro_export]` has no effect on declarative macro definitions
pub macro foo() {}

// `#[macro_export]` on `macro_rules!` is valid and should not emit unused_attributes
#[macro_export]
macro_rules! bar {
() => {};
}

fn main() {}
Loading