Skip to content

Commit cf9db76

Browse files
committed
hygiene: Require passing transparency explicitly to apply_mark
1 parent b0c4d0f commit cf9db76

File tree

6 files changed

+66
-74
lines changed

6 files changed

+66
-74
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,17 +1388,3 @@ impl<'feat> ExpansionConfig<'feat> {
13881388
self.features.map_or(false, |features| features.custom_inner_attributes)
13891389
}
13901390
}
1391-
1392-
// A Marker adds the given mark to the syntax context.
1393-
#[derive(Debug)]
1394-
pub struct Marker(pub ExpnId);
1395-
1396-
impl MutVisitor for Marker {
1397-
fn visit_span(&mut self, span: &mut Span) {
1398-
*span = span.apply_mark(self.0)
1399-
}
1400-
1401-
fn visit_mac(&mut self, mac: &mut ast::Mac) {
1402-
noop_visit_mac(mac, self)
1403-
}
1404-
}

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 13 additions & 8 deletions
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,7 @@ pub fn compile(
473478
SyntaxExtension {
474479
kind: SyntaxExtensionKind::LegacyBang(expander),
475480
span: def.span,
476-
default_transparency,
481+
default_transparency: transparency,
477482
allow_internal_unstable,
478483
allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe),
479484
local_inner_macros,

src/libsyntax/ext/tt/transcribe.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
1-
use crate::ast::Ident;
1+
use crate::ast::{Ident, Mac};
22
use crate::ext::base::ExtCtxt;
3-
use crate::ext::expand::Marker;
43
use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
54
use crate::ext::tt::quoted;
6-
use crate::mut_visit::noop_visit_tt;
5+
use crate::mut_visit::{self, MutVisitor};
76
use crate::parse::token::{self, NtTT, Token};
87
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
98

109
use smallvec::{smallvec, SmallVec};
1110

1211
use rustc_data_structures::fx::FxHashMap;
1312
use rustc_data_structures::sync::Lrc;
13+
use syntax_pos::hygiene::{ExpnId, Transparency};
14+
use syntax_pos::Span;
15+
1416
use std::mem;
1517

18+
// A Marker adds the given mark to the syntax context.
19+
struct Marker(ExpnId, Transparency);
20+
21+
impl MutVisitor for Marker {
22+
fn visit_span(&mut self, span: &mut Span) {
23+
*span = span.apply_mark(self.0, self.1)
24+
}
25+
26+
fn visit_mac(&mut self, mac: &mut Mac) {
27+
mut_visit::noop_visit_mac(mac, self)
28+
}
29+
}
30+
31+
impl Marker {
32+
fn visit_delim_span(&mut self, dspan: &mut DelimSpan) {
33+
self.visit_span(&mut dspan.open);
34+
self.visit_span(&mut dspan.close);
35+
}
36+
}
37+
1638
/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
1739
enum Frame {
1840
Delimited { forest: Lrc<quoted::Delimited>, idx: usize, span: DelimSpan },
@@ -68,6 +90,7 @@ pub(super) fn transcribe(
6890
cx: &ExtCtxt<'_>,
6991
interp: &FxHashMap<Ident, NamedMatch>,
7092
src: Vec<quoted::TokenTree>,
93+
transparency: Transparency,
7194
) -> TokenStream {
7295
// Nothing for us to transcribe...
7396
if src.is_empty() {
@@ -96,6 +119,7 @@ pub(super) fn transcribe(
96119
// again, and we are done transcribing.
97120
let mut result: Vec<TreeAndJoint> = Vec::new();
98121
let mut result_stack = Vec::new();
122+
let mut marker = Marker(cx.current_expansion.id, transparency);
99123

100124
loop {
101125
// Look at the last frame on the stack.
@@ -207,7 +231,7 @@ pub(super) fn transcribe(
207231
}
208232

209233
// Replace the meta-var with the matched token tree from the invocation.
210-
quoted::TokenTree::MetaVar(mut sp, ident) => {
234+
quoted::TokenTree::MetaVar(mut sp, mut ident) => {
211235
// Find the matched nonterminal from the macro invocation, and use it to replace
212236
// the meta-var.
213237
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
@@ -218,7 +242,7 @@ pub(super) fn transcribe(
218242
if let NtTT(ref tt) = **nt {
219243
result.push(tt.clone().into());
220244
} else {
221-
sp = sp.apply_mark(cx.current_expansion.id);
245+
marker.visit_span(&mut sp);
222246
let token = TokenTree::token(token::Interpolated(nt.clone()), sp);
223247
result.push(token.into());
224248
}
@@ -232,9 +256,8 @@ pub(super) fn transcribe(
232256
} else {
233257
// If we aren't able to match the meta-var, we push it back into the result but
234258
// with modified syntax context. (I believe this supports nested macros).
235-
let ident =
236-
Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.id));
237-
sp = sp.apply_mark(cx.current_expansion.id);
259+
marker.visit_span(&mut sp);
260+
marker.visit_ident(&mut ident);
238261
result.push(TokenTree::token(token::Dollar, sp).into());
239262
result.push(TokenTree::Token(Token::from_ast_ident(ident)).into());
240263
}
@@ -246,17 +269,16 @@ pub(super) fn transcribe(
246269
// jump back out of the Delimited, pop the result_stack and add the new results back to
247270
// the previous results (from outside the Delimited).
248271
quoted::TokenTree::Delimited(mut span, delimited) => {
249-
span = span.apply_mark(cx.current_expansion.id);
272+
marker.visit_delim_span(&mut span);
250273
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
251274
result_stack.push(mem::take(&mut result));
252275
}
253276

254277
// Nothing much to do here. Just push the token to the result, being careful to
255278
// preserve syntax context.
256279
quoted::TokenTree::Token(token) => {
257-
let mut marker = Marker(cx.current_expansion.id);
258280
let mut tt = TokenTree::Token(token);
259-
noop_visit_tt(&mut tt, &mut marker);
281+
marker.visit_tt(&mut tt);
260282
result.push(tt.into());
261283
}
262284

src/libsyntax/tokenstream.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::parse::Directory;
1919
use crate::parse::token::{self, DelimToken, Token, TokenKind};
2020
use crate::print::pprust;
2121

22-
use syntax_pos::{BytePos, ExpnId, Span, DUMMY_SP};
22+
use syntax_pos::{BytePos, Span, DUMMY_SP};
2323
#[cfg(target_arch = "x86_64")]
2424
use rustc_data_structures::static_assert_size;
2525
use rustc_data_structures::sync::Lrc;
@@ -547,11 +547,4 @@ impl DelimSpan {
547547
pub fn entire(self) -> Span {
548548
self.open.with_hi(self.close.hi())
549549
}
550-
551-
pub fn apply_mark(self, expn_id: ExpnId) -> Self {
552-
DelimSpan {
553-
open: self.open.apply_mark(expn_id),
554-
close: self.close.apply_mark(expn_id),
555-
}
556-
}
557550
}

src/libsyntax_pos/hygiene.rs

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ impl HygieneData {
192192
self.syntax_context_data[ctxt.0 as usize].parent
193193
}
194194

195-
fn remove_mark(&self, ctxt: &mut SyntaxContext) -> ExpnId {
196-
let outer_expn = self.outer_expn(*ctxt);
195+
fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) {
196+
let outer_mark = self.outer_mark(*ctxt);
197197
*ctxt = self.parent_ctxt(*ctxt);
198-
outer_expn
198+
outer_mark
199199
}
200200

201201
fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
@@ -218,20 +218,14 @@ impl HygieneData {
218218
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
219219
let mut scope = None;
220220
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
221-
scope = Some(self.remove_mark(ctxt));
221+
scope = Some(self.remove_mark(ctxt).0);
222222
}
223223
scope
224224
}
225225

226-
fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext {
227-
assert_ne!(expn_id, ExpnId::root());
228-
self.apply_mark_with_transparency(
229-
ctxt, expn_id, self.expn_data(expn_id).default_transparency
230-
)
231-
}
232-
233-
fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId,
234-
transparency: Transparency) -> SyntaxContext {
226+
fn apply_mark(
227+
&mut self, ctxt: SyntaxContext, expn_id: ExpnId, transparency: Transparency
228+
) -> SyntaxContext {
235229
assert_ne!(expn_id, ExpnId::root());
236230
if transparency == Transparency::Opaque {
237231
return self.apply_mark_internal(ctxt, expn_id, transparency);
@@ -365,15 +359,9 @@ impl SyntaxContext {
365359
SyntaxContext(raw)
366360
}
367361

368-
/// Extend a syntax context with a given expansion and default transparency for that expansion.
369-
pub fn apply_mark(self, expn_id: ExpnId) -> SyntaxContext {
370-
HygieneData::with(|data| data.apply_mark(self, expn_id))
371-
}
372-
373362
/// Extend a syntax context with a given expansion and transparency.
374-
pub fn apply_mark_with_transparency(self, expn_id: ExpnId, transparency: Transparency)
375-
-> SyntaxContext {
376-
HygieneData::with(|data| data.apply_mark_with_transparency(self, expn_id, transparency))
363+
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
364+
HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
377365
}
378366

379367
/// Pulls a single mark off of the syntax context. This effectively moves the
@@ -393,7 +381,7 @@ impl SyntaxContext {
393381
/// invocation of f that created g1.
394382
/// Returns the mark that was removed.
395383
pub fn remove_mark(&mut self) -> ExpnId {
396-
HygieneData::with(|data| data.remove_mark(self))
384+
HygieneData::with(|data| data.remove_mark(self).0)
397385
}
398386

399387
pub fn marks(self) -> Vec<(ExpnId, Transparency)> {
@@ -466,8 +454,8 @@ impl SyntaxContext {
466454
let mut scope = None;
467455
let mut glob_ctxt = data.modern(glob_span.ctxt());
468456
while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
469-
scope = Some(data.remove_mark(&mut glob_ctxt));
470-
if data.remove_mark(self) != scope.unwrap() {
457+
scope = Some(data.remove_mark(&mut glob_ctxt).0);
458+
if data.remove_mark(self).0 != scope.unwrap() {
471459
return None;
472460
}
473461
}
@@ -498,9 +486,9 @@ impl SyntaxContext {
498486
marks.push(data.remove_mark(&mut glob_ctxt));
499487
}
500488

501-
let scope = marks.last().cloned();
502-
while let Some(mark) = marks.pop() {
503-
*self = data.apply_mark(*self, mark);
489+
let scope = marks.last().map(|mark| mark.0);
490+
while let Some((expn_id, transparency)) = marks.pop() {
491+
*self = data.apply_mark(*self, expn_id, transparency);
504492
}
505493
Some(scope)
506494
})
@@ -571,9 +559,7 @@ impl Span {
571559
) -> Span {
572560
HygieneData::with(|data| {
573561
let expn_id = data.fresh_expn(Some(expn_data));
574-
self.with_ctxt(data.apply_mark_with_transparency(
575-
SyntaxContext::root(), expn_id, transparency
576-
))
562+
self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
577563
})
578564
}
579565
}

src/libsyntax_pos/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,13 +517,13 @@ impl Span {
517517
/// given ID and transparency, assuming that macro was defined directly and not produced by
518518
/// some other macro (which is the case for built-in and procedural macros).
519519
pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
520-
self.with_ctxt(SyntaxContext::root().apply_mark_with_transparency(expn_id, transparency))
520+
self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
521521
}
522522

523523
#[inline]
524-
pub fn apply_mark(self, mark: ExpnId) -> Span {
524+
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
525525
let span = self.data();
526-
span.with_ctxt(span.ctxt.apply_mark(mark))
526+
span.with_ctxt(span.ctxt.apply_mark(expn_id, transparency))
527527
}
528528

529529
#[inline]

0 commit comments

Comments
 (0)