Skip to content

Commit 5ade61a

Browse files
committed
Auto merge of #63823 - petrochenkov:noapply2, r=matthewjasper
Audit uses of `apply_mark` in built-in macros + Remove default macro transparencies Every use of `apply_mark` in a built-in or procedural macro is supposed to look like this ```rust location.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id)) ``` where `SyntaxContext::root()` means that the built-in/procedural macro is defined directly, rather than expanded from some other macro. However, few people understood what `apply_mark` does, so we had a lot of copy-pasted uses of it looking e.g. like ```rust span = span.apply_mark(ecx.current_expansion.id); ``` , which doesn't really make sense for procedural macros, but at the same time is not too harmful, if the macros use the traditional `macro_rules` hygiene. So, to fight this, we stop using `apply_mark` directly in built-in macro implementations, and follow the example of regular proc macros instead and use analogues of `Span::def_site()` and `Span::call_site()`, which are much more intuitive and less error-prone. - `ecx.with_def_site_ctxt(span)` takes the `span`'s location and combines it with a def-site context. - `ecx.with_call_site_ctxt(span)` takes the `span`'s location and combines it with a call-site context. Even if called multiple times (which sometimes happens due to some historical messiness of the built-in macro code) these functions will produce the same result, unlike `apply_mark` which will grow the mark chain further in this case. --- After `apply_mark`s in built-in macros are eliminated, the remaining `apply_mark`s are very few in number, so we can start passing the previously implicit `Transparency` argument to them explicitly, thus eliminating the need in `default_transparency` fields in hygiene structures and `#[rustc_macro_transparency]` annotations on built-in macros. So, the task of making built-in macros opaque can now be formulated as "eliminate `with_legacy_ctxt` in favor of `with_def_site_ctxt`" rather than "replace `#[rustc_macro_transparency = "semitransparent"]` with `#[rustc_macro_transparency = "opaque"]`". r? @matthewjasper
2 parents 4784645 + 6548a5f commit 5ade61a

28 files changed

+152
-179
lines changed

src/libcore/macros.rs

-8
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,6 @@ pub(crate) mod builtin {
734734
#[allow_internal_unstable(fmt_internals)]
735735
#[rustc_builtin_macro]
736736
#[macro_export]
737-
#[rustc_macro_transparency = "opaque"]
738737
macro_rules! format_args {
739738
($fmt:expr) => ({ /* compiler built-in */ });
740739
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
@@ -747,7 +746,6 @@ pub(crate) mod builtin {
747746
#[allow_internal_unstable(fmt_internals)]
748747
#[rustc_builtin_macro]
749748
#[macro_export]
750-
#[rustc_macro_transparency = "opaque"]
751749
macro_rules! format_args_nl {
752750
($fmt:expr) => ({ /* compiler built-in */ });
753751
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
@@ -1235,42 +1233,36 @@ pub(crate) mod builtin {
12351233
#[stable(feature = "rust1", since = "1.0.0")]
12361234
#[allow_internal_unstable(test, rustc_attrs)]
12371235
#[rustc_builtin_macro]
1238-
#[rustc_macro_transparency = "semitransparent"]
12391236
pub macro test($item:item) { /* compiler built-in */ }
12401237

12411238
/// Attribute macro applied to a function to turn it into a benchmark test.
12421239
#[unstable(feature = "test", issue = "50297",
12431240
reason = "`bench` is a part of custom test frameworks which are unstable")]
12441241
#[allow_internal_unstable(test, rustc_attrs)]
12451242
#[rustc_builtin_macro]
1246-
#[rustc_macro_transparency = "semitransparent"]
12471243
pub macro bench($item:item) { /* compiler built-in */ }
12481244

12491245
/// An implementation detail of the `#[test]` and `#[bench]` macros.
12501246
#[unstable(feature = "custom_test_frameworks", issue = "50297",
12511247
reason = "custom test frameworks are an unstable feature")]
12521248
#[allow_internal_unstable(test, rustc_attrs)]
12531249
#[rustc_builtin_macro]
1254-
#[rustc_macro_transparency = "semitransparent"]
12551250
pub macro test_case($item:item) { /* compiler built-in */ }
12561251

12571252
/// Attribute macro applied to a static to register it as a global allocator.
12581253
#[stable(feature = "global_allocator", since = "1.28.0")]
12591254
#[allow_internal_unstable(rustc_attrs)]
12601255
#[rustc_builtin_macro]
1261-
#[rustc_macro_transparency = "semitransparent"]
12621256
pub macro global_allocator($item:item) { /* compiler built-in */ }
12631257

12641258
/// Unstable implementation detail of the `rustc` compiler, do not use.
12651259
#[rustc_builtin_macro]
1266-
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
12671260
#[stable(feature = "rust1", since = "1.0.0")]
12681261
#[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
12691262
pub macro RustcDecodable($item:item) { /* compiler built-in */ }
12701263

12711264
/// Unstable implementation detail of the `rustc` compiler, do not use.
12721265
#[rustc_builtin_macro]
1273-
#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")]
12741266
#[stable(feature = "rust1", since = "1.0.0")]
12751267
#[allow_internal_unstable(core_intrinsics)]
12761268
pub macro RustcEncodable($item:item) { /* compiler built-in */ }

src/librustc/ich/impls_syntax.rs

-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,6 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
402402
parent -> _,
403403
call_site,
404404
def_site,
405-
default_transparency,
406405
allow_internal_unstable,
407406
allow_internal_unsafe,
408407
local_inner_macros,

src/librustc/ty/query/on_disk_cache.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::mem;
2323
use syntax::ast::NodeId;
2424
use syntax::source_map::{SourceMap, StableSourceFileId};
2525
use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile};
26-
use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnData};
26+
use syntax_pos::hygiene::{ExpnId, SyntaxContext};
2727

2828
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
2929

@@ -593,8 +593,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
593593
// don't seem to be used after HIR lowering, so everything should be fine
594594
// as long as incremental compilation does not kick in before that.
595595
let location = || Span::with_root_ctxt(lo, hi);
596-
let recover_from_expn_data = |this: &Self, expn_data, pos| {
597-
let span = location().fresh_expansion(expn_data);
596+
let recover_from_expn_data = |this: &Self, expn_data, transparency, pos| {
597+
let span = location().fresh_expansion_with_transparency(expn_data, transparency);
598598
this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt());
599599
span
600600
};
@@ -603,9 +603,9 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
603603
location()
604604
}
605605
TAG_EXPN_DATA_INLINE => {
606-
let expn_data = Decodable::decode(self)?;
606+
let (expn_data, transparency) = Decodable::decode(self)?;
607607
recover_from_expn_data(
608-
self, expn_data, AbsoluteBytePos::new(self.opaque.position())
608+
self, expn_data, transparency, AbsoluteBytePos::new(self.opaque.position())
609609
)
610610
}
611611
TAG_EXPN_DATA_SHORTHAND => {
@@ -614,9 +614,9 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
614614
if let Some(ctxt) = cached_ctxt {
615615
Span::new(lo, hi, ctxt)
616616
} else {
617-
let expn_data =
618-
self.with_position(pos.to_usize(), |this| ExpnData::decode(this))?;
619-
recover_from_expn_data(self, expn_data, pos)
617+
let (expn_data, transparency) =
618+
self.with_position(pos.to_usize(), |this| Decodable::decode(this))?;
619+
recover_from_expn_data(self, expn_data, transparency, pos)
620620
}
621621
}
622622
_ => {
@@ -819,15 +819,15 @@ where
819819
if span_data.ctxt == SyntaxContext::root() {
820820
TAG_NO_EXPN_DATA.encode(self)
821821
} else {
822-
let (expn_id, expn_data) = span_data.ctxt.outer_expn_with_data();
822+
let (expn_id, transparency, expn_data) = span_data.ctxt.outer_mark_with_data();
823823
if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() {
824824
TAG_EXPN_DATA_SHORTHAND.encode(self)?;
825825
pos.encode(self)
826826
} else {
827827
TAG_EXPN_DATA_INLINE.encode(self)?;
828828
let pos = AbsoluteBytePos::new(self.position());
829829
self.expn_data_shorthands.insert(expn_id, pos);
830-
expn_data.encode(self)
830+
(expn_data, transparency).encode(self)
831831
}
832832
}
833833
}

src/librustc_resolve/build_reduced_graph.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'a> Resolver<'a> {
145145
}
146146
}
147147

148-
fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
148+
crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
149149
if let Some(ext) = self.macro_map.get(&def_id) {
150150
return Some(ext.clone());
151151
}

src/librustc_resolve/lib.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1647,10 +1647,14 @@ impl<'a> Resolver<'a> {
16471647
if module.expansion != parent.expansion &&
16481648
module.expansion.is_descendant_of(parent.expansion) {
16491649
// The macro is a proc macro derive
1650-
if module.expansion.looks_like_proc_macro_derive() {
1651-
if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) {
1652-
*poisoned = Some(node_id);
1653-
return module.parent;
1650+
if let Some(&def_id) = self.macro_defs.get(&module.expansion) {
1651+
if let Some(ext) = self.get_macro_by_def_id(def_id) {
1652+
if !ext.is_builtin && ext.macro_kind() == MacroKind::Derive {
1653+
if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) {
1654+
*poisoned = Some(node_id);
1655+
return module.parent;
1656+
}
1657+
}
16541658
}
16551659
}
16561660
}

src/libsyntax/ext/base.rs

+23-27
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::attr::{HasAttrs, Stability, Deprecation};
33
use crate::source_map::SourceMap;
44
use crate::edition::Edition;
55
use crate::ext::expand::{self, AstFragment, Invocation};
6-
use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
6+
use crate::ext::hygiene::{ExpnId, Transparency};
77
use crate::mut_visit::{self, MutVisitor};
88
use crate::parse::{self, parser, DirectoryOwnership};
99
use crate::parse::token;
@@ -549,8 +549,6 @@ pub struct SyntaxExtension {
549549
pub kind: SyntaxExtensionKind,
550550
/// Span of the macro definition.
551551
pub span: Span,
552-
/// Hygienic properties of spans produced by this macro by default.
553-
pub default_transparency: Transparency,
554552
/// Whitelist of unstable features that are treated as stable inside this macro.
555553
pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
556554
/// Suppresses the `unsafe_code` lint for code produced by this macro.
@@ -572,22 +570,6 @@ pub struct SyntaxExtension {
572570
pub is_derive_copy: bool,
573571
}
574572

575-
impl SyntaxExtensionKind {
576-
/// When a syntax extension is constructed,
577-
/// its transparency can often be inferred from its kind.
578-
fn default_transparency(&self) -> Transparency {
579-
match self {
580-
SyntaxExtensionKind::Bang(..) |
581-
SyntaxExtensionKind::Attr(..) |
582-
SyntaxExtensionKind::Derive(..) |
583-
SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque,
584-
SyntaxExtensionKind::LegacyBang(..) |
585-
SyntaxExtensionKind::LegacyAttr(..) |
586-
SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent,
587-
}
588-
}
589-
}
590-
591573
impl SyntaxExtension {
592574
/// Returns which kind of macro calls this syntax extension.
593575
pub fn macro_kind(&self) -> MacroKind {
@@ -606,7 +588,6 @@ impl SyntaxExtension {
606588
pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
607589
SyntaxExtension {
608590
span: DUMMY_SP,
609-
default_transparency: kind.default_transparency(),
610591
allow_internal_unstable: None,
611592
allow_internal_unsafe: false,
612593
local_inner_macros: false,
@@ -646,7 +627,6 @@ impl SyntaxExtension {
646627
parent,
647628
call_site,
648629
def_site: self.span,
649-
default_transparency: self.default_transparency,
650630
allow_internal_unstable: self.allow_internal_unstable.clone(),
651631
allow_internal_unsafe: self.allow_internal_unsafe,
652632
local_inner_macros: self.local_inner_macros,
@@ -760,23 +740,39 @@ impl<'a> ExtCtxt<'a> {
760740
pub fn call_site(&self) -> Span {
761741
self.current_expansion.id.expn_data().call_site
762742
}
763-
pub fn backtrace(&self) -> SyntaxContext {
764-
SyntaxContext::root().apply_mark(self.current_expansion.id)
743+
744+
/// Equivalent of `Span::def_site` from the proc macro API,
745+
/// except that the location is taken from the span passed as an argument.
746+
pub fn with_def_site_ctxt(&self, span: Span) -> Span {
747+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque)
748+
}
749+
750+
/// Equivalent of `Span::call_site` from the proc macro API,
751+
/// except that the location is taken from the span passed as an argument.
752+
pub fn with_call_site_ctxt(&self, span: Span) -> Span {
753+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent)
754+
}
755+
756+
/// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
757+
/// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
758+
/// or with `with_call_site_ctxt` (where necessary).
759+
pub fn with_legacy_ctxt(&self, span: Span) -> Span {
760+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent)
765761
}
766762

767763
/// Returns span for the macro which originally caused the current expansion to happen.
768764
///
769765
/// Stops backtracing at include! boundary.
770766
pub fn expansion_cause(&self) -> Option<Span> {
771-
let mut ctxt = self.backtrace();
767+
let mut expn_id = self.current_expansion.id;
772768
let mut last_macro = None;
773769
loop {
774-
let expn_data = ctxt.outer_expn_data();
770+
let expn_data = expn_id.expn_data();
775771
// Stop going up the backtrace once include! is encountered
776772
if expn_data.is_root() || expn_data.kind.descr() == sym::include {
777773
break;
778774
}
779-
ctxt = expn_data.call_site.ctxt();
775+
expn_id = expn_data.call_site.ctxt().outer_expn();
780776
last_macro = Some(expn_data.call_site);
781777
}
782778
last_macro
@@ -865,7 +861,7 @@ impl<'a> ExtCtxt<'a> {
865861
ast::Ident::from_str(st)
866862
}
867863
pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
868-
let def_site = DUMMY_SP.apply_mark(self.current_expansion.id);
864+
let def_site = self.with_def_site_ctxt(DUMMY_SP);
869865
iter::once(Ident::new(kw::DollarCrate, def_site))
870866
.chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
871867
.collect()

src/libsyntax/ext/expand.rs

-15
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
565565
return fragment_kind.dummy(span);
566566
}
567567
let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path };
568-
let span = span.with_ctxt(self.cx.backtrace());
569568
let items = expander.expand(self.cx, span, &meta, item);
570569
fragment_kind.expect_from_annotatables(items)
571570
}
@@ -1389,17 +1388,3 @@ impl<'feat> ExpansionConfig<'feat> {
13891388
self.features.map_or(false, |features| features.custom_inner_attributes)
13901389
}
13911390
}
1392-
1393-
// A Marker adds the given mark to the syntax context.
1394-
#[derive(Debug)]
1395-
pub struct Marker(pub ExpnId);
1396-
1397-
impl MutVisitor for Marker {
1398-
fn visit_span(&mut self, span: &mut Span) {
1399-
*span = span.apply_mark(self.0)
1400-
}
1401-
1402-
fn visit_mac(&mut self, mac: &mut ast::Mac) {
1403-
noop_visit_mac(mac, self)
1404-
}
1405-
}

src/libsyntax/ext/proc_macro_server.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}
77
use errors::{Diagnostic, DiagnosticBuilder};
88
use rustc_data_structures::sync::Lrc;
99
use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
10-
use syntax_pos::hygiene::{SyntaxContext, Transparency};
1110
use syntax_pos::symbol::{kw, sym, Symbol};
1211

1312
use proc_macro::{Delimiter, Level, LineColumn, Spacing};
@@ -363,16 +362,10 @@ impl<'a> Rustc<'a> {
363362
pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
364363
// No way to determine def location for a proc macro right now, so use call location.
365364
let location = cx.current_expansion.id.expn_data().call_site;
366-
let to_span = |transparency| {
367-
location.with_ctxt(
368-
SyntaxContext::root()
369-
.apply_mark_with_transparency(cx.current_expansion.id, transparency),
370-
)
371-
};
372365
Rustc {
373366
sess: cx.parse_sess,
374-
def_site: to_span(Transparency::Opaque),
375-
call_site: to_span(Transparency::Transparent),
367+
def_site: cx.with_def_site_ctxt(location),
368+
call_site: cx.with_call_site_ctxt(location),
376369
}
377370
}
378371

src/libsyntax/ext/tt/macro_rules.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{ast, attr, attr::TransparencyError};
1919

2020
use errors::{DiagnosticBuilder, FatalError};
2121
use log::debug;
22+
use syntax_pos::hygiene::Transparency;
2223
use syntax_pos::Span;
2324

2425
use rustc_data_structures::fx::FxHashMap;
@@ -128,6 +129,7 @@ impl<'a> ParserAnyMacro<'a> {
128129
struct MacroRulesMacroExpander {
129130
name: ast::Ident,
130131
span: Span,
132+
transparency: Transparency,
131133
lhses: Vec<quoted::TokenTree>,
132134
rhses: Vec<quoted::TokenTree>,
133135
valid: bool,
@@ -143,7 +145,9 @@ impl TTMacroExpander for MacroRulesMacroExpander {
143145
if !self.valid {
144146
return DummyResult::any(sp);
145147
}
146-
generic_extension(cx, sp, self.span, self.name, input, &self.lhses, &self.rhses)
148+
generic_extension(
149+
cx, sp, self.span, self.name, self.transparency, input, &self.lhses, &self.rhses
150+
)
147151
}
148152
}
149153

@@ -158,6 +162,7 @@ fn generic_extension<'cx>(
158162
sp: Span,
159163
def_span: Span,
160164
name: ast::Ident,
165+
transparency: Transparency,
161166
arg: TokenStream,
162167
lhses: &[quoted::TokenTree],
163168
rhses: &[quoted::TokenTree],
@@ -187,7 +192,7 @@ fn generic_extension<'cx>(
187192

188193
let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>();
189194
// rhs has holes ( `$id` and `$(...)` that need filled)
190-
let mut tts = transcribe(cx, &named_matches, rhs);
195+
let mut tts = transcribe(cx, &named_matches, rhs, transparency);
191196

192197
// Replace all the tokens for the corresponding positions in the macro, to maintain
193198
// proper positions in error reporting, while maintaining the macro_backtrace.
@@ -415,11 +420,7 @@ pub fn compile(
415420
// that is not lint-checked and trigger the "failed to process buffered lint here" bug.
416421
valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
417422

418-
let expander: Box<_> =
419-
Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid });
420-
421-
let (default_transparency, transparency_error) =
422-
attr::find_transparency(&def.attrs, body.legacy);
423+
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
423424
match transparency_error {
424425
Some(TransparencyError::UnknownTransparency(value, span)) =>
425426
sess.span_diagnostic.span_err(
@@ -432,6 +433,10 @@ pub fn compile(
432433
None => {}
433434
}
434435

436+
let expander: Box<_> = Box::new(MacroRulesMacroExpander {
437+
name: def.ident, span: def.span, transparency, lhses, rhses, valid
438+
});
439+
435440
let allow_internal_unstable =
436441
attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| {
437442
attr.meta_item_list()
@@ -473,7 +478,6 @@ pub fn compile(
473478
SyntaxExtension {
474479
kind: SyntaxExtensionKind::LegacyBang(expander),
475480
span: def.span,
476-
default_transparency,
477481
allow_internal_unstable,
478482
allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe),
479483
local_inner_macros,

0 commit comments

Comments
 (0)