Skip to content

Commit 0fb01d2

Browse files
committed
Audit uses of apply_mark in built-in macros
Replace them with equivalents of `Span::{def_site,call_site}` from proc macro API. The new API is much less error prone and doesn't rely on macros having default transparency.
1 parent 7602267 commit 0fb01d2

File tree

19 files changed

+56
-41
lines changed

19 files changed

+56
-41
lines changed

src/libsyntax/ext/base.rs

Lines changed: 23 additions & 7 deletions
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;
@@ -760,23 +760,39 @@ impl<'a> ExtCtxt<'a> {
760760
pub fn call_site(&self) -> Span {
761761
self.current_expansion.id.expn_data().call_site
762762
}
763-
pub fn backtrace(&self) -> SyntaxContext {
764-
SyntaxContext::root().apply_mark(self.current_expansion.id)
763+
764+
/// Equivalent of `Span::def_site` from the proc macro API,
765+
/// except that the location is taken from the span passed as an argument.
766+
pub fn with_def_site_ctxt(&self, span: Span) -> Span {
767+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque)
768+
}
769+
770+
/// Equivalent of `Span::call_site` from the proc macro API,
771+
/// except that the location is taken from the span passed as an argument.
772+
pub fn with_call_site_ctxt(&self, span: Span) -> Span {
773+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent)
774+
}
775+
776+
/// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
777+
/// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
778+
/// or with `with_call_site_ctxt` (where necessary).
779+
pub fn with_legacy_ctxt(&self, span: Span) -> Span {
780+
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent)
765781
}
766782

767783
/// Returns span for the macro which originally caused the current expansion to happen.
768784
///
769785
/// Stops backtracing at include! boundary.
770786
pub fn expansion_cause(&self) -> Option<Span> {
771-
let mut ctxt = self.backtrace();
787+
let mut expn_id = self.current_expansion.id;
772788
let mut last_macro = None;
773789
loop {
774-
let expn_data = ctxt.outer_expn_data();
790+
let expn_data = expn_id.expn_data();
775791
// Stop going up the backtrace once include! is encountered
776792
if expn_data.is_root() || expn_data.kind.descr() == sym::include {
777793
break;
778794
}
779-
ctxt = expn_data.call_site.ctxt();
795+
expn_id = expn_data.call_site.ctxt().outer_expn();
780796
last_macro = Some(expn_data.call_site);
781797
}
782798
last_macro
@@ -865,7 +881,7 @@ impl<'a> ExtCtxt<'a> {
865881
ast::Ident::from_str(st)
866882
}
867883
pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
868-
let def_site = DUMMY_SP.apply_mark(self.current_expansion.id);
884+
let def_site = self.with_def_site_ctxt(DUMMY_SP);
869885
iter::once(Ident::new(kw::DollarCrate, def_site))
870886
.chain(components.iter().map(|&s| Ident::with_dummy_span(s)))
871887
.collect()

src/libsyntax/ext/expand.rs

Lines changed: 0 additions & 1 deletion
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
}

src/libsyntax/ext/proc_macro_server.rs

Lines changed: 2 additions & 9 deletions
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/asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
6363
MacEager::expr(P(ast::Expr {
6464
id: ast::DUMMY_NODE_ID,
6565
node: ast::ExprKind::InlineAsm(P(inline_asm)),
66-
span: sp.with_ctxt(cx.backtrace()),
66+
span: cx.with_legacy_ctxt(sp),
6767
attrs: ThinVec::new(),
6868
}))
6969
}

src/libsyntax_ext/assert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn expand_assert<'cx>(
2323
}
2424
};
2525

26-
let sp = sp.apply_mark(cx.current_expansion.id);
26+
let sp = cx.with_legacy_ctxt(sp);
2727
let panic_call = Mac {
2828
path: Path::from_ident(Ident::new(sym::panic, sp)),
2929
tts: custom_message.unwrap_or_else(|| {

src/libsyntax_ext/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn expand_cfg(
1616
sp: Span,
1717
tts: &[tokenstream::TokenTree],
1818
) -> Box<dyn base::MacResult + 'static> {
19-
let sp = sp.apply_mark(cx.current_expansion.id);
19+
let sp = cx.with_legacy_ctxt(sp);
2020

2121
match parse_cfg(cx, sp, tts) {
2222
Ok(cfg) => {

src/libsyntax_ext/concat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,6 @@ pub fn expand_syntax_ext(
5959
} else if has_errors {
6060
return DummyResult::any(sp);
6161
}
62-
let sp = sp.apply_mark(cx.current_expansion.id);
62+
let sp = cx.with_legacy_ctxt(sp);
6363
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
6464
}

src/libsyntax_ext/concat_idents.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>,
3939
}
4040
}
4141

42-
let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.id));
42+
let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp));
4343

4444
struct ConcatIdentsResult { ident: ast::Ident }
4545

src/libsyntax_ext/deriving/clone.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ fn cs_clone_shallow(name: &str,
112112
ty: P<ast::Ty>, span: Span, helper_name: &str) {
113113
// Generate statement `let _: helper_name<ty>;`,
114114
// set the expn ID so we can use the unstable struct.
115-
let span = span.with_ctxt(cx.backtrace());
115+
let span = cx.with_def_site_ctxt(span);
116116
let assert_path = cx.path_all(span, true,
117117
cx.std_path(&[sym::clone, Symbol::intern(helper_name)]),
118118
vec![GenericArg::Type(ty)], vec![]);

src/libsyntax_ext/deriving/cmp/eq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>,
5353
ty: P<ast::Ty>, span: Span, helper_name: &str) {
5454
// Generate statement `let _: helper_name<ty>;`,
5555
// set the expn ID so we can use the unstable struct.
56-
let span = span.with_ctxt(cx.backtrace());
56+
let span = cx.with_def_site_ctxt(span);
5757
let assert_path = cx.path_all(span, true,
5858
cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]),
5959
vec![GenericArg::Type(ty)], vec![]);

src/libsyntax_ext/deriving/debug.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
6060
};
6161

6262
// We want to make sure we have the ctxt set so that we can use unstable methods
63-
let span = span.with_ctxt(cx.backtrace());
63+
let span = cx.with_def_site_ctxt(span);
6464
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
6565
let builder = Ident::from_str_and_span("debug_trait_builder", span);
6666
let builder_expr = cx.expr_ident(span, builder.clone());

src/libsyntax_ext/deriving/generic/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<'a> Path<'a> {
8585
PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()),
8686
PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
8787
PathKind::Std => {
88-
let def_site = DUMMY_SP.apply_mark(cx.current_expansion.id);
88+
let def_site = cx.with_def_site_ctxt(DUMMY_SP);
8989
idents.insert(0, Ident::new(kw::DollarCrate, def_site));
9090
cx.path_all(span, false, idents, params, Vec::new())
9191
}

src/libsyntax_ext/deriving/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ impl MultiItemModifier for BuiltinDerive {
4848
meta_item: &MetaItem,
4949
item: Annotatable)
5050
-> Vec<Annotatable> {
51+
// FIXME: Built-in derives often forget to give spans contexts,
52+
// so we are doing it here in a centralized way.
53+
let span = ecx.with_def_site_ctxt(span);
5154
let mut items = Vec::new();
5255
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
5356
items
@@ -60,7 +63,7 @@ fn call_intrinsic(cx: &ExtCtxt<'_>,
6063
intrinsic: &str,
6164
args: Vec<P<ast::Expr>>)
6265
-> P<ast::Expr> {
63-
let span = span.with_ctxt(cx.backtrace());
66+
let span = cx.with_def_site_ctxt(span);
6467
let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]);
6568
let call = cx.expr_call_global(span, path, args);
6669

src/libsyntax_ext/env.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
2020
Some(v) => v,
2121
};
2222

23-
let sp = sp.apply_mark(cx.current_expansion.id);
23+
let sp = cx.with_legacy_ctxt(sp);
2424
let e = match env::var(&*var.as_str()) {
2525
Err(..) => {
2626
let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));

src/libsyntax_ext/format.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use syntax::parse::token;
1212
use syntax::ptr::P;
1313
use syntax::symbol::{Symbol, sym};
1414
use syntax::tokenstream;
15-
use syntax_pos::{MultiSpan, Span, DUMMY_SP};
15+
use syntax_pos::{MultiSpan, Span};
1616

1717
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1818
use std::borrow::Cow;
@@ -666,8 +666,7 @@ impl<'a, 'b> Context<'a, 'b> {
666666
// passed to this function.
667667
for (i, e) in self.args.into_iter().enumerate() {
668668
let name = names_pos[i];
669-
let span =
670-
DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.id));
669+
let span = self.ecx.with_def_site_ctxt(e.span);
671670
pats.push(self.ecx.pat_ident(span, name));
672671
for ref arg_ty in self.arg_unique_types[i].iter() {
673672
locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
@@ -745,7 +744,7 @@ impl<'a, 'b> Context<'a, 'b> {
745744
ty: &ArgumentType,
746745
arg: ast::Ident,
747746
) -> P<ast::Expr> {
748-
sp = sp.apply_mark(ecx.current_expansion.id);
747+
sp = ecx.with_def_site_ctxt(sp);
749748
let arg = ecx.expr_ident(sp, arg);
750749
let trait_ = match *ty {
751750
Placeholder(ref tyname) => {
@@ -798,7 +797,7 @@ fn expand_format_args_impl<'cx>(
798797
tts: &[tokenstream::TokenTree],
799798
nl: bool,
800799
) -> Box<dyn base::MacResult + 'cx> {
801-
sp = sp.apply_mark(ecx.current_expansion.id);
800+
sp = ecx.with_def_site_ctxt(sp);
802801
match parse_args(ecx, sp, tts) {
803802
Ok((efmt, args, names)) => {
804803
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl))
@@ -842,7 +841,7 @@ pub fn expand_preparsed_format_args(
842841
let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
843842

844843
let mut macsp = ecx.call_site();
845-
macsp = macsp.with_ctxt(ecx.backtrace());
844+
macsp = ecx.with_def_site_ctxt(macsp);
846845

847846
let msg = "format argument must be a string literal";
848847
let fmt_sp = efmt.span;

src/libsyntax_ext/global_allocator.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use syntax::ast::{self, Arg, Attribute, Expr, FnHeader, Generics, Ident};
33
use syntax::attr::check_builtin_macro_attribute;
44
use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
55
use syntax::ext::base::{Annotatable, ExtCtxt};
6-
use syntax::ext::hygiene::SyntaxContext;
76
use syntax::ptr::P;
87
use syntax::symbol::{kw, sym, Symbol};
98
use syntax_pos::Span;
@@ -29,7 +28,7 @@ pub fn expand(
2928
};
3029

3130
// Generate a bunch of new items using the AllocFnFactory
32-
let span = item.span.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id));
31+
let span = ecx.with_legacy_ctxt(item.span);
3332
let f = AllocFnFactory {
3433
span,
3534
kind: AllocatorKind::Global,

src/libsyntax_ext/global_asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
3030
id: ast::DUMMY_NODE_ID,
3131
node: ast::ItemKind::GlobalAsm(P(global_asm)),
3232
vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
33-
span: sp.with_ctxt(cx.backtrace()),
33+
span: cx.with_legacy_ctxt(sp),
3434
tokens: None,
3535
})])
3636
}

src/libsyntax_ext/test.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
use syntax::ast;
55
use syntax::attr::{self, check_builtin_macro_attribute};
66
use syntax::ext::base::*;
7-
use syntax::ext::hygiene::SyntaxContext;
87
use syntax::print::pprust;
98
use syntax::source_map::respan;
109
use syntax::symbol::{Symbol, sym};
@@ -29,7 +28,7 @@ pub fn expand_test_case(
2928

3029
if !ecx.ecfg.should_test { return vec![]; }
3130

32-
let sp = attr_sp.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id));
31+
let sp = ecx.with_legacy_ctxt(attr_sp);
3332
let mut item = anno_item.expect_item();
3433
item = item.map(|mut item| {
3534
item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
@@ -93,8 +92,7 @@ pub fn expand_test_or_bench(
9392
return vec![Annotatable::Item(item)];
9493
}
9594

96-
let ctxt = SyntaxContext::root().apply_mark(cx.current_expansion.id);
97-
let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt));
95+
let (sp, attr_sp) = (cx.with_legacy_ctxt(item.span), cx.with_legacy_ctxt(attr_sp));
9896

9997
// Gensym "test" so we can extern crate without conflicting with any local names
10098
let test_id = cx.ident_of("test").gensym();

src/libsyntax_pos/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub mod edition;
2222
use edition::Edition;
2323
pub mod hygiene;
2424
pub use hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind, MacroKind, DesugaringKind};
25+
use hygiene::Transparency;
2526

2627
mod span_encoding;
2728
pub use span_encoding::{Span, DUMMY_SP};
@@ -512,6 +513,13 @@ impl Span {
512513
span.ctxt)
513514
}
514515

516+
/// Produces a span with the same location as `self` and context produced by a macro with the
517+
/// given ID and transparency, assuming that macro was defined directly and not produced by
518+
/// some other macro (which is the case for built-in and procedural macros).
519+
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))
521+
}
522+
515523
#[inline]
516524
pub fn apply_mark(self, mark: ExpnId) -> Span {
517525
let span = self.data();

0 commit comments

Comments
 (0)