Skip to content

Commit 20d23d8

Browse files
committed
Auto merge of #26347 - nagisa:macro-exp, r=nrc
r? @nrc, because breakage was caused by #25318
2 parents 713d917 + 09ed27c commit 20d23d8

File tree

4 files changed

+106
-72
lines changed

4 files changed

+106
-72
lines changed

src/libsyntax/codemap.rs

+44-53
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! within the CodeMap, which upon request can be converted to line and column
1818
//! information, source code snippets, etc.
1919
20-
pub use self::MacroFormat::*;
20+
pub use self::ExpnFormat::*;
2121

2222
use std::cell::RefCell;
2323
use std::ops::{Add, Sub};
@@ -228,17 +228,17 @@ pub struct FileMapAndBytePos { pub fm: Rc<FileMap>, pub pos: BytePos }
228228

229229

230230
// _____________________________________________________________________________
231-
// MacroFormat, NameAndSpan, ExpnInfo, ExpnId
231+
// ExpnFormat, NameAndSpan, ExpnInfo, ExpnId
232232
//
233233

234-
/// The syntax with which a macro was invoked.
235-
#[derive(Clone, Copy, Hash, Debug)]
236-
pub enum MacroFormat {
234+
/// The source of expansion.
235+
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
236+
pub enum ExpnFormat {
237237
/// e.g. #[derive(...)] <item>
238238
MacroAttribute,
239239
/// e.g. `format!()`
240240
MacroBang,
241-
/// Expansion performed by the compiler (libsyntax::expand).
241+
/// Syntax sugar expansion performed by the compiler (libsyntax::expand).
242242
CompilerExpansion,
243243
}
244244

@@ -248,7 +248,7 @@ pub struct NameAndSpan {
248248
/// with this Span.
249249
pub name: String,
250250
/// The format with which the macro was invoked.
251-
pub format: MacroFormat,
251+
pub format: ExpnFormat,
252252
/// Whether the macro is allowed to use #[unstable]/feature-gated
253253
/// features internally without forcing the whole crate to opt-in
254254
/// to them.
@@ -259,11 +259,11 @@ pub struct NameAndSpan {
259259
pub span: Option<Span>
260260
}
261261

262-
/// Extra information for tracking macro expansion of spans
262+
/// Extra information for tracking spans of macro and syntax sugar expansion
263263
#[derive(Hash, Debug)]
264264
pub struct ExpnInfo {
265-
/// The location of the actual macro invocation, e.g. `let x =
266-
/// foo!();`
265+
/// The location of the actual macro invocation or syntax sugar , e.g.
266+
/// `let x = foo!();` or `if let Some(y) = x {}`
267267
///
268268
/// This may recursively refer to other macro invocations, e.g. if
269269
/// `foo!()` invoked `bar!()` internally, and there was an
@@ -272,12 +272,7 @@ pub struct ExpnInfo {
272272
/// call_site span would have its own ExpnInfo, with the call_site
273273
/// pointing to the `foo!` invocation.
274274
pub call_site: Span,
275-
/// Information about the macro and its definition.
276-
///
277-
/// The `callee` of the inner expression in the `call_site`
278-
/// example would point to the `macro_rules! bar { ... }` and that
279-
/// of the `bar!()` invocation would point to the `macro_rules!
280-
/// foo { ... }`.
275+
/// Information about the expansion.
281276
pub callee: NameAndSpan
282277
}
283278

@@ -677,7 +672,39 @@ impl CodeMap {
677672

678673
/// Lookup source information about a BytePos
679674
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
680-
self.lookup_pos(pos)
675+
let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
676+
let line = a + 1; // Line numbers start at 1
677+
let chpos = self.bytepos_to_file_charpos(pos);
678+
let linebpos = (*f.lines.borrow())[a];
679+
let linechpos = self.bytepos_to_file_charpos(linebpos);
680+
debug!("byte pos {:?} is on the line at byte pos {:?}",
681+
pos, linebpos);
682+
debug!("char pos {:?} is on the line at char pos {:?}",
683+
chpos, linechpos);
684+
debug!("byte is on line: {}", line);
685+
assert!(chpos >= linechpos);
686+
Loc {
687+
file: f,
688+
line: line,
689+
col: chpos - linechpos
690+
}
691+
}
692+
693+
fn lookup_line(&self, pos: BytePos) -> FileMapAndLine {
694+
let idx = self.lookup_filemap_idx(pos);
695+
696+
let files = self.files.borrow();
697+
let f = (*files)[idx].clone();
698+
let mut a = 0;
699+
{
700+
let lines = f.lines.borrow();
701+
let mut b = lines.len();
702+
while b - a > 1 {
703+
let m = (a + b) / 2;
704+
if (*lines)[m] > pos { b = m; } else { a = m; }
705+
}
706+
}
707+
FileMapAndLine {fm: f, line: a}
681708
}
682709

683710
pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
@@ -877,42 +904,6 @@ impl CodeMap {
877904
return a;
878905
}
879906

880-
fn lookup_line(&self, pos: BytePos) -> FileMapAndLine {
881-
let idx = self.lookup_filemap_idx(pos);
882-
883-
let files = self.files.borrow();
884-
let f = (*files)[idx].clone();
885-
let mut a = 0;
886-
{
887-
let lines = f.lines.borrow();
888-
let mut b = lines.len();
889-
while b - a > 1 {
890-
let m = (a + b) / 2;
891-
if (*lines)[m] > pos { b = m; } else { a = m; }
892-
}
893-
}
894-
FileMapAndLine {fm: f, line: a}
895-
}
896-
897-
fn lookup_pos(&self, pos: BytePos) -> Loc {
898-
let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
899-
let line = a + 1; // Line numbers start at 1
900-
let chpos = self.bytepos_to_file_charpos(pos);
901-
let linebpos = (*f.lines.borrow())[a];
902-
let linechpos = self.bytepos_to_file_charpos(linebpos);
903-
debug!("byte pos {:?} is on the line at byte pos {:?}",
904-
pos, linebpos);
905-
debug!("char pos {:?} is on the line at char pos {:?}",
906-
chpos, linechpos);
907-
debug!("byte is on line: {}", line);
908-
assert!(chpos >= linechpos);
909-
Loc {
910-
file: f,
911-
line: line,
912-
col: chpos - linechpos
913-
}
914-
}
915-
916907
pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId {
917908
let mut expansions = self.expansions.borrow_mut();
918909
expansions.push(expn_info);

src/libsyntax/ext/base.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*;
1313
use ast;
1414
use ast::Name;
1515
use codemap;
16-
use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
16+
use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion};
1717
use ext;
1818
use ext::expand;
1919
use ext::tt::macro_rules;
@@ -658,6 +658,8 @@ impl<'a> ExtCtxt<'a> {
658658
})
659659
}
660660
pub fn backtrace(&self) -> ExpnId { self.backtrace }
661+
662+
/// Original span that caused the current exapnsion to happen.
661663
pub fn original_span(&self) -> Span {
662664
let mut expn_id = self.backtrace;
663665
let mut call_site = None;
@@ -672,26 +674,31 @@ impl<'a> ExtCtxt<'a> {
672674
}
673675
call_site.expect("missing expansion backtrace")
674676
}
675-
pub fn original_span_in_file(&self) -> Span {
677+
678+
/// Returns span for the macro which originally caused the current expansion to happen.
679+
///
680+
/// Stops backtracing at include! boundary.
681+
pub fn expansion_cause(&self) -> Span {
676682
let mut expn_id = self.backtrace;
677-
let mut call_site = None;
683+
let mut last_macro = None;
678684
loop {
679-
let expn_info = self.codemap().with_expn_info(expn_id, |ei| {
680-
ei.map(|ei| (ei.call_site, ei.callee.name == "include"))
681-
});
682-
match expn_info {
683-
None => break,
684-
Some((cs, is_include)) => {
685-
if is_include {
686-
// Don't recurse into file using "include!".
687-
break;
685+
if self.codemap().with_expn_info(expn_id, |info| {
686+
info.map_or(None, |i| {
687+
if i.callee.name == "include" {
688+
// Stop going up the backtrace once include! is encountered
689+
return None;
688690
}
689-
call_site = Some(cs);
690-
expn_id = cs.expn_id;
691-
}
691+
expn_id = i.call_site.expn_id;
692+
if i.callee.format != CompilerExpansion {
693+
last_macro = Some(i.call_site)
694+
}
695+
return Some(());
696+
})
697+
}).is_none() {
698+
break
692699
}
693700
}
694-
call_site.expect("missing expansion backtrace")
701+
last_macro.expect("missing expansion backtrace")
695702
}
696703

697704
pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }

src/libsyntax/ext/source_util.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
3434
-> Box<base::MacResult+'static> {
3535
base::check_zero_tts(cx, sp, tts, "line!");
3636

37-
let topmost = cx.original_span_in_file();
37+
let topmost = cx.expansion_cause();
3838
let loc = cx.codemap().lookup_char_pos(topmost.lo);
3939

4040
base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
@@ -45,7 +45,7 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
4545
-> Box<base::MacResult+'static> {
4646
base::check_zero_tts(cx, sp, tts, "column!");
4747

48-
let topmost = cx.original_span_in_file();
48+
let topmost = cx.expansion_cause();
4949
let loc = cx.codemap().lookup_char_pos(topmost.lo);
5050

5151
base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
@@ -58,7 +58,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
5858
-> Box<base::MacResult+'static> {
5959
base::check_zero_tts(cx, sp, tts, "file!");
6060

61-
let topmost = cx.original_span_in_file();
61+
let topmost = cx.expansion_cause();
6262
let loc = cx.codemap().lookup_char_pos(topmost.lo);
6363
let filename = token::intern_and_get_ident(&loc.file.name);
6464
base::MacEager::expr(cx.expr_str(topmost, filename))

src/test/run-pass/issue-26322.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! columnline {
12+
() => (
13+
(column!(), line!())
14+
)
15+
}
16+
17+
macro_rules! indirectcolumnline {
18+
() => (
19+
(||{ columnline!() })()
20+
)
21+
}
22+
23+
fn main() {
24+
let closure = || {
25+
columnline!()
26+
};
27+
let iflet = if let Some(_) = Some(0) {
28+
columnline!()
29+
} else { (0, 0) };
30+
let cl = columnline!();
31+
assert_eq!(closure(), (8, 25));
32+
assert_eq!(iflet, (8, 28));
33+
assert_eq!(cl, (13, 30));
34+
let indirect = indirectcolumnline!();
35+
assert_eq!(indirect, (19, 34));
36+
}

0 commit comments

Comments
 (0)