Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub(crate) mod on_type_error;
pub(crate) mod on_unimplemented;
pub(crate) mod on_unknown;
pub(crate) mod on_unmatched_args;
pub(crate) mod opaque;

#[derive(Copy, Clone)]
pub(crate) enum Mode {
Expand Down
64 changes: 64 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/diagnostic/opaque.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use rustc_feature::AttributeStability;
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::{Span, sym};

use crate::attributes::{AcceptMapping, AttributeParser};
use crate::context::{AcceptContext, FinalizeContext};
use crate::diagnostics::OpaqueDoesNotExpectArgs;
use crate::parser::ArgParser;
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::Allow;
use crate::{template, unstable};

#[derive(Default)]
pub(crate) struct OpaqueParser {
attr_span: Option<Span>,
}

impl AttributeParser for OpaqueParser {
const ATTRIBUTES: AcceptMapping<Self> = &[
(
&[sym::diagnostic, sym::opaque],
template!(Word),
AttributeStability::Stable, // Unstable, stability checked manually in the parser
|this, cx, args| {
if !cx.features().diagnostic_opaque() {
return;
}
this.parse(cx, args);
},
),
(
// For use on exported macros, where using tool attributes is an error.
&[sym::rustc_diagnostic_opaque],
template!(Word),
unstable!(
rustc_attrs,
"see `#[diagnostic::opaque]` for the nightly equivalent of this attribute"
),
OpaqueParser::parse,
),
];
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::MacroDef)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(_) = self.attr_span { Some(AttributeKind::Opaque) } else { None }
}
}

impl OpaqueParser {
fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser) {
let attr_span = cx.attr_span;
if let Some(earlier_span) = self.attr_span {
cx.warn_unused_duplicate(earlier_span, attr_span);
}
self.attr_span = Some(attr_span);
Comment thread
mejrs marked this conversation as resolved.

if !matches!(args, ArgParser::NoArgs) {
cx.emit_lint(MALFORMED_DIAGNOSTIC_ATTRIBUTES, OpaqueDoesNotExpectArgs, attr_span);
}
}
}
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 @@ -36,6 +36,7 @@ use crate::attributes::diagnostic::on_type_error::*;
use crate::attributes::diagnostic::on_unimplemented::*;
use crate::attributes::diagnostic::on_unknown::*;
use crate::attributes::diagnostic::on_unmatched_args::*;
use crate::attributes::diagnostic::opaque::*;
use crate::attributes::doc::*;
use crate::attributes::dummy::*;
use crate::attributes::inline::*;
Expand Down Expand Up @@ -151,6 +152,7 @@ attribute_parsers!(
OnUnimplementedParser,
OnUnknownParser,
OnUnmatchedArgsParser,
OpaqueParser,
RustcAlignParser,
RustcAlignStaticParser,
RustcCguTestAttributeParser,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ pub(crate) struct AttrCrateLevelOnly;
#[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")]
pub(crate) struct DoNotRecommendDoesNotExpectArgs;

#[derive(Diagnostic)]
#[diag("`#[diagnostic::opaque]` does not expect any arguments")]
pub(crate) struct OpaqueDoesNotExpectArgs;

#[derive(Diagnostic)]
#[diag("invalid `crate_type` value")]
pub(crate) struct UnknownCrateTypes {
Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub trait Emitter {
ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,

ExpnKind::Macro(macro_kind, name) => {
Some((macro_kind, name, expn_data.hide_backtrace))
Some((macro_kind, name, expn_data.diagnostic_opaque))
}
}
})
Expand All @@ -188,8 +188,7 @@ pub trait Emitter {
self.render_multispans_macro_backtrace(span, children, backtrace);

if !backtrace {
// Skip builtin macros, as their expansion isn't relevant to the end user. This includes
// actual intrinsics, like `asm!`.
// Skip macros annotated with `#[diagnostic::opaque]`. Builtin macros are "opaque" too.
if let Some((macro_kind, name, _)) = has_macro_spans.first()
&& let Some((_, _, false)) = has_macro_spans.last()
{
Expand Down Expand Up @@ -334,18 +333,25 @@ pub trait Emitter {
// we move these spans from the external macros to their corresponding use site.
fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
let Some(source_map) = self.source_map() else { return };
let should_hide = |span| {
source_map.is_imported(span) || {
let expn = span.data().ctxt.outer_expn_data();
expn.diagnostic_opaque && matches!(expn.kind, ExpnKind::Macro(MacroKind::Bang, _))
}
};

// First, find all the spans in external macros and point instead at their use site.
let replacements: Vec<(Span, Span)> = span
.primary_spans()
.iter()
.copied()
.chain(span.span_labels().iter().map(|sp_label| sp_label.span))
.filter_map(|sp| {
if !sp.is_dummy() && source_map.is_imported(sp) {
if !sp.is_dummy() && should_hide(sp) {
let mut span = sp;
while let Some(callsite) = span.parent_callsite() {
span = callsite;
if !source_map.is_imported(span) {
if !should_hide(span) {
return Some((sp, span));
}
}
Expand Down
21 changes: 8 additions & 13 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,9 +804,9 @@ pub struct SyntaxExtension {
/// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
/// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
pub collapse_debuginfo: bool,
/// Suppresses the "this error originates in the macro" note when a diagnostic points at this
/// macro.
pub hide_backtrace: bool,
/// Prevents diagnostics pointing into this macro and suppresses the "this error originates in
/// the macro" note when a diagnostic points at this macro.
pub diagnostic_opaque: bool,
}

impl SyntaxExtension {
Expand Down Expand Up @@ -840,7 +840,7 @@ impl SyntaxExtension {
allow_internal_unsafe: false,
local_inner_macros: false,
collapse_debuginfo: false,
hide_backtrace: false,
diagnostic_opaque: false,
}
}

Expand Down Expand Up @@ -870,12 +870,6 @@ impl SyntaxExtension {
collapse_table[flag as usize][attr as usize]
}

fn get_hide_backtrace(attrs: &[hir::Attribute]) -> bool {
// FIXME(estebank): instead of reusing `#[rustc_diagnostic_item]` as a proxy, introduce a
// new attribute purely for this under the `#[diagnostic]` namespace.
find_attr!(attrs, RustcDiagnosticItem(..))
}

/// Constructs a syntax extension with the given properties
/// and other properties converted from attributes.
pub fn new(
Expand Down Expand Up @@ -910,7 +904,8 @@ impl SyntaxExtension {
// Not a built-in macro
None => (None, helper_attrs),
};
let hide_backtrace = builtin_name.is_some() || Self::get_hide_backtrace(attrs);
let diagnostic_opaque = builtin_name.is_some()
|| (!sess.opts.unstable_opts.macro_backtrace && find_attr!(attrs, Opaque));

let stability = find_attr!(attrs, Stability { stability, .. } => *stability);

Expand Down Expand Up @@ -938,7 +933,7 @@ impl SyntaxExtension {
allow_internal_unsafe,
local_inner_macros,
collapse_debuginfo,
hide_backtrace,
diagnostic_opaque,
}
}

Expand Down Expand Up @@ -1024,7 +1019,7 @@ impl SyntaxExtension {
self.allow_internal_unsafe,
self.local_inner_macros,
self.collapse_debuginfo,
self.hide_backtrace,
self.diagnostic_opaque,
)
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
// Used by the `rustc::bad_opt_access` lint on fields
// types (as well as any others in future).
sym::rustc_lint_opt_deny_field_access,
sym::rustc_diagnostic_opaque,

// ==========================================================================
// Internal attributes, Const related:
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@ declare_features! (
(unstable, diagnostic_on_unknown, "1.96.0", Some(152900)),
/// Allows macros to customize macro argument matcher diagnostics.
(unstable, diagnostic_on_unmatched_args, "1.97.0", Some(155642)),
// Used by macros to not show their bodies in error messages. No-op with `-Z macro-backtrace`.
(unstable, diagnostic_opaque, "CURRENT_RUSTC_VERSION", Some(158813)),
/// Allows `#[doc(cfg(...))]`.
(unstable, doc_cfg, "1.21.0", Some(43781)),
/// Allows `#[doc(masked)]`.
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,9 @@ pub enum AttributeKind {
directive: Option<Box<Directive>>,
},

/// Represents `#[diagnostic::opaque]`.
Opaque,

/// Represents `#[optimize(size|speed)]`
Optimize(OptimizeAttr, Span),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl AttributeKind {
OnUnimplemented { .. } => Yes,
OnUnknown { .. } => Yes,
OnUnmatchedArgs { .. } => Yes,
Opaque => Yes,
Optimize(..) => No,
PanicRuntime => No,
PatchableFunctionEntry { .. } => Yes,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::NoStd { .. } => (),
AttributeKind::OnUnknown { .. } => (),
AttributeKind::OnUnmatchedArgs { .. } => (),
AttributeKind::Opaque => (),
AttributeKind::Optimize(..) => (),
AttributeKind::PanicRuntime => (),
AttributeKind::PatchableFunctionEntry { .. } => (),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
(sym::on_unknown, Some(sym::diagnostic_on_unknown)),
(sym::on_unmatched_args, Some(sym::diagnostic_on_unmatched_args)),
(sym::on_type_error, Some(sym::diagnostic_on_type_error)),
(sym::opaque, Some(sym::diagnostic_opaque)),
];

if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,9 @@ pub struct ExpnData {
/// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
/// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
pub(crate) collapse_debuginfo: bool,
/// When true, we do not display the note telling people to use the `-Zmacro-backtrace` flag.
pub hide_backtrace: bool,
/// When true, we prevent diagnostics pointing into this macro, if it is one, and we do not
/// display the note telling people to use the `-Zmacro-backtrace` flag.
pub diagnostic_opaque: bool,
}

impl !PartialEq for ExpnData {}
Expand All @@ -1040,7 +1041,7 @@ impl ExpnData {
allow_internal_unsafe: bool,
local_inner_macros: bool,
collapse_debuginfo: bool,
hide_backtrace: bool,
diagnostic_opaque: bool,
) -> ExpnData {
ExpnData {
kind,
Expand All @@ -1055,7 +1056,7 @@ impl ExpnData {
allow_internal_unsafe,
local_inner_macros,
collapse_debuginfo,
hide_backtrace,
diagnostic_opaque,
}
}

Expand All @@ -1080,7 +1081,7 @@ impl ExpnData {
allow_internal_unsafe: false,
local_inner_macros: false,
collapse_debuginfo: false,
hide_backtrace: false,
diagnostic_opaque: false,
}
}

Expand Down
31 changes: 18 additions & 13 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,20 +1238,25 @@ impl Span {
/// If "self" is the span of the outer_ident, and "within" is the span of the `($ident,)`
/// expr, then this will return the span of the `$ident` macro variable.
pub fn within_macro(self, within: Span, sm: &SourceMap) -> Option<Span> {
match Span::prepare_to_combine(self, within) {
// Only return something if it doesn't overlap with the original span,
// and the span isn't "imported" (i.e. from unavailable sources).
// FIXME: This does limit the usefulness of the error when the macro is
// from a foreign crate; we could also take into account `-Zmacro-backtrace`,
// which doesn't redact this span (but that would mean passing in even more
// args to this function, lol).
Ok((self_, _, parent))
if self_.hi < self.lo() || self.hi() < self_.lo && !sm.is_imported(within) =>
{
Some(Span::new(self_.lo, self_.hi, self_.ctxt, parent))
}
_ => None,
let (self_, _, parent) = Span::prepare_to_combine(self, within).ok()?;

// Only return something if it doesn't overlap with the original span
// and the span isn't "imported" (i.e. from unavailable sources).
// FIXME: This does limit the usefulness of the error when the macro is
// from a foreign crate; we could also take into account `-Zmacro-backtrace`,
// which doesn't redact this span (but that would mean passing in even more
// args to this function, lol).
if self.data().contains(self_) || sm.is_imported(within) {
return None;
}

// Don't return something if it's marked with `#[diagnostic::opaque]`.
// This already accounts for `-Zmacro-backtrace`.
if within.data().ctxt.outer_expn_data().diagnostic_opaque {
return None;
}

Some(Span::new(self_.lo, self_.hi, self_.ctxt, parent))
}

pub fn from_inner(self, inner: InnerSpan) -> Span {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ symbols! {
diagnostic_on_unknown,
diagnostic_on_unmatch_args,
diagnostic_on_unmatched_args,
diagnostic_opaque,
dialect,
direct,
discriminant_kind,
Expand Down Expand Up @@ -1775,6 +1776,7 @@ symbols! {
rustc_deprecated_safe_2024,
rustc_diagnostic_item,
rustc_diagnostic_macros,
rustc_diagnostic_opaque,
rustc_do_not_const_check,
rustc_doc_primitive,
rustc_driver,
Expand Down
2 changes: 2 additions & 0 deletions library/alloc/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "vec_macro"]
#[allow_internal_unstable(rustc_attrs, liballoc_internals)]
#[rustc_diagnostic_opaque]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
Expand Down Expand Up @@ -108,6 +109,7 @@ macro_rules! vec {
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(hint_must_use, liballoc_internals)]
#[rustc_diagnostic_item = "format_macro"]
#[rustc_diagnostic_opaque]
macro_rules! format {
($($arg:tt)*) => {
$crate::__export::must_use({
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
#![feature(derive_const)]
#![feature(diagnostic_on_const)]
#![feature(diagnostic_on_unmatched_args)]
#![feature(diagnostic_opaque)]
#![feature(doc_cfg)]
#![feature(doc_notable_trait)]
#![feature(extern_types)]
Expand Down
Loading
Loading