Skip to content

Commit f329991

Browse files
committed
Auto merge of #51762 - petrochenkov:oh-hi-mark, r=<try>
hygiene: Implement transparent marks and use them for call-site hygiene in proc-macros Fixes #50050
2 parents 01cc982 + 463033f commit f329991

File tree

40 files changed

+485
-168
lines changed

40 files changed

+485
-168
lines changed

src/libproc_macro/diagnostic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl Diagnostic {
9797
/// Emit the diagnostic.
9898
#[unstable(feature = "proc_macro", issue = "38356")]
9999
pub fn emit(self) {
100-
::__internal::with_sess(move |(sess, _)| {
100+
::__internal::with_sess(move |sess, _| {
101101
let handler = &sess.span_diagnostic;
102102
let level = __internal::level_to_internal_level(self.level);
103103
let mut diag = rustc::DiagnosticBuilder::new(handler, level, &*self.message);

src/libproc_macro/lib.rs

+55-37
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ use syntax::parse::{self, token};
5858
use syntax::symbol::{keywords, Symbol};
5959
use syntax::tokenstream;
6060
use syntax::parse::lexer::{self, comments};
61-
use syntax_pos::{FileMap, Pos, SyntaxContext, FileName};
62-
use syntax_pos::hygiene::Mark;
61+
use syntax_pos::{FileMap, Pos, FileName};
6362

6463
/// The main type provided by this crate, representing an abstract stream of
6564
/// tokens, or, more specifically, a sequence of token trees.
@@ -109,6 +108,7 @@ impl TokenStream {
109108
/// Attempts to break the string into tokens and parse those tokens into a token stream.
110109
/// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
111110
/// or characters not existing in the language.
111+
/// All tokens in the parsed stream get `Span::call_site()` spans.
112112
///
113113
/// NOTE: Some errors may cause panics instead of returning `LexError`. We reserve the right to
114114
/// change these errors into `LexError`s later.
@@ -117,17 +117,10 @@ impl FromStr for TokenStream {
117117
type Err = LexError;
118118

119119
fn from_str(src: &str) -> Result<TokenStream, LexError> {
120-
__internal::with_sess(|(sess, mark)| {
121-
let src = src.to_string();
122-
let name = FileName::ProcMacroSourceCode;
123-
let expn_info = mark.expn_info().unwrap();
124-
let call_site = expn_info.call_site;
125-
// notify the expansion info that it is unhygienic
126-
let mark = Mark::fresh(mark);
127-
mark.set_expn_info(expn_info);
128-
let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
129-
let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
130-
Ok(__internal::token_stream_wrap(stream))
120+
__internal::with_sess(|sess, data| {
121+
Ok(__internal::token_stream_wrap(parse::parse_stream_from_source_str(
122+
FileName::ProcMacroSourceCode, src.to_string(), sess, Some(data.call_site.0)
123+
)))
131124
})
132125
}
133126
}
@@ -184,8 +177,6 @@ impl iter::FromIterator<TokenStream> for TokenStream {
184177
#[unstable(feature = "proc_macro", issue = "38356")]
185178
pub mod token_stream {
186179
use syntax::tokenstream;
187-
use syntax_pos::DUMMY_SP;
188-
189180
use {TokenTree, TokenStream, Delimiter};
190181

191182
/// An iterator over `TokenStream`'s `TokenTree`s.
@@ -214,7 +205,7 @@ pub mod token_stream {
214205
// need to flattened during iteration over stream's token trees.
215206
// Eventually this needs to be removed in favor of keeping original token trees
216207
// and not doing the roundtrip through AST.
217-
if tree.span().0 == DUMMY_SP {
208+
if tree.span().0.is_dummy() {
218209
if let TokenTree::Group(ref group) = tree {
219210
if group.delimiter() == Delimiter::None {
220211
self.cursor.insert(group.stream.clone().0);
@@ -284,10 +275,7 @@ impl Span {
284275
/// A span that resolves at the macro definition site.
285276
#[unstable(feature = "proc_macro", issue = "38356")]
286277
pub fn def_site() -> Span {
287-
::__internal::with_sess(|(_, mark)| {
288-
let call_site = mark.expn_info().unwrap().call_site;
289-
Span(call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
290-
})
278+
::__internal::with_sess(|_, data| data.def_site)
291279
}
292280

293281
/// The span of the invocation of the current procedural macro.
@@ -296,7 +284,7 @@ impl Span {
296284
/// at the macro call site will be able to refer to them as well.
297285
#[unstable(feature = "proc_macro", issue = "38356")]
298286
pub fn call_site() -> Span {
299-
::__internal::with_sess(|(_, mark)| Span(mark.expn_info().unwrap().call_site))
287+
::__internal::with_sess(|_, data| data.call_site)
300288
}
301289

302290
/// The original source file into which this span points.
@@ -1243,7 +1231,7 @@ impl TokenTree {
12431231
}
12441232

12451233
Interpolated(_) => {
1246-
__internal::with_sess(|(sess, _)| {
1234+
__internal::with_sess(|sess, _| {
12471235
let tts = token.interpolated_to_tokenstream(sess, span);
12481236
tt!(Group::new(Delimiter::None, TokenStream(tts)))
12491237
})
@@ -1354,20 +1342,21 @@ pub mod __internal {
13541342
pub use quote::{LiteralKind, SpannedSymbol, Quoter, unquote};
13551343

13561344
use std::cell::Cell;
1345+
use std::ptr;
13571346

13581347
use syntax::ast;
13591348
use syntax::ext::base::ExtCtxt;
1360-
use syntax::ext::hygiene::Mark;
13611349
use syntax::ptr::P;
13621350
use syntax::parse::{self, ParseSess};
13631351
use syntax::parse::token::{self, Token};
13641352
use syntax::tokenstream;
13651353
use syntax_pos::{BytePos, Loc, DUMMY_SP};
1354+
use syntax_pos::hygiene::{Mark, SyntaxContext, Transparency};
13661355

1367-
use super::{TokenStream, LexError};
1356+
use super::{TokenStream, LexError, Span};
13681357

13691358
pub fn lookup_char_pos(pos: BytePos) -> Loc {
1370-
with_sess(|(sess, _)| sess.codemap().lookup_char_pos(pos))
1359+
with_sess(|sess, _| sess.codemap().lookup_char_pos(pos))
13711360
}
13721361

13731362
pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
@@ -1380,7 +1369,7 @@ pub mod __internal {
13801369
}
13811370

13821371
pub fn token_stream_parse_items(stream: TokenStream) -> Result<Vec<P<ast::Item>>, LexError> {
1383-
with_sess(move |(sess, _)| {
1372+
with_sess(move |sess, _| {
13841373
let mut parser = parse::stream_to_parser(sess, stream.0);
13851374
let mut items = Vec::new();
13861375

@@ -1411,16 +1400,30 @@ pub mod __internal {
14111400
expand: fn(TokenStream) -> TokenStream);
14121401
}
14131402

1403+
#[derive(Clone, Copy)]
1404+
pub struct ProcMacroData {
1405+
pub def_site: Span,
1406+
pub call_site: Span,
1407+
}
1408+
1409+
#[derive(Clone, Copy)]
1410+
struct ProcMacroSess {
1411+
parse_sess: *const ParseSess,
1412+
data: ProcMacroData,
1413+
}
1414+
14141415
// Emulate scoped_thread_local!() here essentially
14151416
thread_local! {
1416-
static CURRENT_SESS: Cell<(*const ParseSess, Mark)> =
1417-
Cell::new((0 as *const _, Mark::root()));
1417+
static CURRENT_SESS: Cell<ProcMacroSess> = Cell::new(ProcMacroSess {
1418+
parse_sess: ptr::null(),
1419+
data: ProcMacroData { def_site: Span(DUMMY_SP), call_site: Span(DUMMY_SP) },
1420+
});
14181421
}
14191422

14201423
pub fn set_sess<F, R>(cx: &ExtCtxt, f: F) -> R
14211424
where F: FnOnce() -> R
14221425
{
1423-
struct Reset { prev: (*const ParseSess, Mark) }
1426+
struct Reset { prev: ProcMacroSess }
14241427

14251428
impl Drop for Reset {
14261429
fn drop(&mut self) {
@@ -1430,24 +1433,39 @@ pub mod __internal {
14301433

14311434
CURRENT_SESS.with(|p| {
14321435
let _reset = Reset { prev: p.get() };
1433-
p.set((cx.parse_sess, cx.current_expansion.mark));
1436+
1437+
// No way to determine def location for a proc macro rigth now, so use call location.
1438+
let location = cx.current_expansion.mark.expn_info().unwrap().call_site;
1439+
// Opaque mark was already created by expansion, now create its transparent twin.
1440+
let opaque_mark = cx.current_expansion.mark;
1441+
let transparent_mark = Mark::fresh_cloned(opaque_mark);
1442+
transparent_mark.set_transparency(Transparency::Transparent);
1443+
1444+
let to_span = |mark| Span(location.with_ctxt(SyntaxContext::empty().apply_mark(mark)));
1445+
p.set(ProcMacroSess {
1446+
parse_sess: cx.parse_sess,
1447+
data: ProcMacroData {
1448+
def_site: to_span(opaque_mark),
1449+
call_site: to_span(transparent_mark),
1450+
},
1451+
});
14341452
f()
14351453
})
14361454
}
14371455

14381456
pub fn in_sess() -> bool
14391457
{
1440-
let p = CURRENT_SESS.with(|p| p.get());
1441-
!p.0.is_null()
1458+
!CURRENT_SESS.with(|sess| sess.get()).parse_sess.is_null()
14421459
}
14431460

14441461
pub fn with_sess<F, R>(f: F) -> R
1445-
where F: FnOnce((&ParseSess, Mark)) -> R
1462+
where F: FnOnce(&ParseSess, &ProcMacroData) -> R
14461463
{
1447-
let p = CURRENT_SESS.with(|p| p.get());
1448-
assert!(!p.0.is_null(), "proc_macro::__internal::with_sess() called \
1449-
before set_parse_sess()!");
1450-
f(unsafe { (&*p.0, p.1) })
1464+
let sess = CURRENT_SESS.with(|sess| sess.get());
1465+
if sess.parse_sess.is_null() {
1466+
panic!("procedural macro API is used outside of a procedural macro");
1467+
}
1468+
f(unsafe { &*sess.parse_sess }, &sess.data)
14511469
}
14521470
}
14531471

src/librustc/hir/map/definitions.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -486,12 +486,7 @@ impl Definitions {
486486
#[inline]
487487
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
488488
if def_id.krate == LOCAL_CRATE {
489-
let span = self.def_index_to_span.get(&def_id.index).cloned().unwrap_or(DUMMY_SP);
490-
if span != DUMMY_SP {
491-
Some(span)
492-
} else {
493-
None
494-
}
489+
self.def_index_to_span.get(&def_id.index).cloned()
495490
} else {
496491
None
497492
}
@@ -588,8 +583,8 @@ impl Definitions {
588583
self.opaque_expansions_that_defined.insert(index, expansion);
589584
}
590585

591-
// The span is added if it isn't DUMMY_SP
592-
if span != DUMMY_SP {
586+
// The span is added if it isn't dummy
587+
if !span.is_dummy() {
593588
self.def_index_to_span.insert(index, span);
594589
}
595590

src/librustc/middle/stability.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use ty::{self, TyCtxt};
2020
use middle::privacy::AccessLevels;
2121
use session::DiagnosticMessageId;
2222
use syntax::symbol::Symbol;
23-
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
23+
use syntax_pos::{Span, MultiSpan};
2424
use syntax::ast;
2525
use syntax::ast::{NodeId, Attribute};
2626
use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};
@@ -687,7 +687,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
687687
let msp: MultiSpan = span.into();
688688
let cm = &self.sess.parse_sess.codemap();
689689
let span_key = msp.primary_span().and_then(|sp: Span|
690-
if sp != DUMMY_SP {
690+
if !sp.is_dummy() {
691691
let file = cm.lookup_char_pos(sp.lo()).file;
692692
if file.name.is_macros() {
693693
None
@@ -725,7 +725,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
725725
match item.node {
726726
hir::ItemExternCrate(_) => {
727727
// compiler-generated `extern crate` items have a dummy span.
728-
if item.span == DUMMY_SP { return }
728+
if item.span.is_dummy() { return }
729729

730730
let def_id = self.tcx.hir.local_def_id(item.id);
731731
let cnum = match self.tcx.extern_mod_stmt_cnum(def_id) {

src/librustc/ty/query/plumbing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ macro_rules! define_queries {
708708

709709
// FIXME(eddyb) Get more valid Span's on queries.
710710
pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
711-
if span != DUMMY_SP {
711+
if !span.is_dummy() {
712712
return span;
713713
}
714714
// The def_span query is used to calculate default_span,

src/librustc_codegen_llvm/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
16621662
let var_scope = get_namespace_for_item(cx, def_id);
16631663
let span = tcx.def_span(def_id);
16641664

1665-
let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
1665+
let (file_metadata, line_number) = if !span.is_dummy() {
16661666
let loc = span_start(cx, span);
16671667
(file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
16681668
} else {

src/librustc_codegen_llvm/debuginfo/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
219219
let span = mir.span;
220220

221221
// This can be the case for functions inlined from another crate
222-
if span == syntax_pos::DUMMY_SP {
222+
if span.is_dummy() {
223223
// FIXME(simulacrum): Probably can't happen; remove.
224224
return FunctionDebugContext::FunctionWithoutDebugInfo;
225225
}

src/librustc_errors/emitter.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use self::Destination::*;
1212

13-
use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
13+
use syntax_pos::{FileMap, Span, MultiSpan};
1414

1515
use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId};
1616
use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
@@ -216,7 +216,7 @@ impl EmitterWriter {
216216

217217
if let Some(ref cm) = self.cm {
218218
for span_label in msp.span_labels() {
219-
if span_label.span == DUMMY_SP {
219+
if span_label.span.is_dummy() {
220220
continue;
221221
}
222222

@@ -730,7 +730,7 @@ impl EmitterWriter {
730730
let mut max = 0;
731731
if let Some(ref cm) = self.cm {
732732
for primary_span in msp.primary_spans() {
733-
if primary_span != &DUMMY_SP {
733+
if !primary_span.is_dummy() {
734734
let hi = cm.lookup_char_pos(primary_span.hi());
735735
if hi.line > max {
736736
max = hi.line;
@@ -739,7 +739,7 @@ impl EmitterWriter {
739739
}
740740
if !self.short_message {
741741
for span_label in msp.span_labels() {
742-
if span_label.span != DUMMY_SP {
742+
if !span_label.span.is_dummy() {
743743
let hi = cm.lookup_char_pos(span_label.span.hi());
744744
if hi.line > max {
745745
max = hi.line;
@@ -778,7 +778,7 @@ impl EmitterWriter {
778778

779779
// First, find all the spans in <*macros> and point instead at their use site
780780
for sp in span.primary_spans() {
781-
if *sp == DUMMY_SP {
781+
if sp.is_dummy() {
782782
continue;
783783
}
784784
let call_sp = cm.call_span_if_macro(*sp);
@@ -790,7 +790,7 @@ impl EmitterWriter {
790790
// Only show macro locations that are local
791791
// and display them like a span_note
792792
if let Some(def_site) = trace.def_site_span {
793-
if def_site == DUMMY_SP {
793+
if def_site.is_dummy() {
794794
continue;
795795
}
796796
if always_backtrace {
@@ -830,7 +830,7 @@ impl EmitterWriter {
830830
span.push_span_label(label_span, label_text);
831831
}
832832
for sp_label in span.span_labels() {
833-
if sp_label.span == DUMMY_SP {
833+
if sp_label.span.is_dummy() {
834834
continue;
835835
}
836836
if cm.span_to_filename(sp_label.span.clone()).is_macros() &&
@@ -1003,7 +1003,7 @@ impl EmitterWriter {
10031003
// Make sure our primary file comes first
10041004
let (primary_lo, cm) = if let (Some(cm), Some(ref primary_span)) =
10051005
(self.cm.as_ref(), msp.primary_span().as_ref()) {
1006-
if primary_span != &&DUMMY_SP {
1006+
if !primary_span.is_dummy() {
10071007
(cm.lookup_char_pos(primary_span.lo()), cm)
10081008
} else {
10091009
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;

src/librustc_metadata/creader.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,11 @@ impl<'a> CrateLoader<'a> {
569569
fn register_bang_proc_macro(&mut self,
570570
name: &str,
571571
expand: fn(TokenStream) -> TokenStream) {
572-
let expand = SyntaxExtension::ProcMacro(
573-
Box::new(BangProcMacro { inner: expand }), false, self.edition
574-
);
572+
let expand = SyntaxExtension::ProcMacro {
573+
expander: Box::new(BangProcMacro { inner: expand }),
574+
allow_internal_unstable: false,
575+
edition: self.edition,
576+
};
575577
self.extensions.push((Symbol::intern(name), Lrc::new(expand)));
576578
}
577579
}

src/librustc_metadata/cstore_impl.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,11 @@ impl CrateStore for cstore::CStore {
518518
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
519519
} else if data.name == "proc_macro" &&
520520
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
521-
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter),
522-
true, data.root.edition);
521+
let ext = SyntaxExtension::ProcMacro {
522+
expander: Box::new(::proc_macro::__internal::Quoter),
523+
allow_internal_unstable: true,
524+
edition: data.root.edition,
525+
};
523526
return LoadedMacro::ProcMacro(Lrc::new(ext));
524527
}
525528

0 commit comments

Comments
 (0)