about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2015-06-16 21:47:09 +0300
committerSimonas Kazlauskas <git@kazlauskas.me>2015-06-16 21:47:09 +0300
commit7ff55eaf258a708217fd9e4b998ee050375c385d (patch)
tree75dd220739b075e2c796257fe50ea42dd9808dce /src/libsyntax/ext
parent73fb19c04ac227fe2aad2c618f76b6eb05dd7ec9 (diff)
downloadrust-7ff55eaf258a708217fd9e4b998ee050375c385d.tar.gz
rust-7ff55eaf258a708217fd9e4b998ee050375c385d.zip
Fix file!(), line!() and column!() macros
These used to return wrong results in case they were expanded inside compiler’s
iternal syntax sugar (closures, if-let) expansions

Fixes #26322
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs41
-rw-r--r--src/libsyntax/ext/source_util.rs6
2 files changed, 28 insertions, 19 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index c2ed3583835..ce4ed9f2158 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*;
 use ast;
 use ast::Name;
 use codemap;
-use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
+use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion};
 use ext;
 use ext::expand;
 use ext::tt::macro_rules;
@@ -658,6 +658,8 @@ impl<'a> ExtCtxt<'a> {
         })
     }
     pub fn backtrace(&self) -> ExpnId { self.backtrace }
+
+    /// Original span that caused the current exapnsion to happen.
     pub fn original_span(&self) -> Span {
         let mut expn_id = self.backtrace;
         let mut call_site = None;
@@ -672,26 +674,33 @@ impl<'a> ExtCtxt<'a> {
         }
         call_site.expect("missing expansion backtrace")
     }
-    pub fn original_span_in_file(&self) -> Span {
+
+    /// Returns span for the macro which originally caused the current expansion to happen.
+    ///
+    /// Stops backtracing at include! boundary.
+    pub fn expansion_cause(&self) -> Span {
         let mut expn_id = self.backtrace;
-        let mut call_site = None;
+        let mut last_macro = None;
+        let mut current_expn = None;
         loop {
-            let expn_info = self.codemap().with_expn_info(expn_id, |ei| {
-                ei.map(|ei| (ei.call_site, ei.callee.name == "include"))
-            });
-            match expn_info {
-                None => break,
-                Some((cs, is_include)) => {
-                    if is_include {
-                        // Don't recurse into file using "include!".
-                        break;
+            if self.codemap().with_expn_info(expn_id, |info| {
+                info.map_or(None, |i| {
+                    if i.callee.name == "include" {
+                        // Stop going up the backtrace once include! is encountered
+                        return None;
                     }
-                    call_site = Some(cs);
-                    expn_id = cs.expn_id;
-                }
+                    expn_id = i.call_site.expn_id;
+                    current_expn = Some(i.call_site);
+                    if i.callee.format != CompilerExpansion {
+                        last_macro = Some(i.call_site)
+                    }
+                    return Some(());
+                })
+            }).is_none() {
+                break
             }
         }
-        call_site.expect("missing expansion backtrace")
+        last_macro.expect("missing expansion backtrace")
     }
 
     pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 08bb4ca1064..3866f5534c2 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -34,7 +34,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "line!");
 
-    let topmost = cx.original_span_in_file();
+    let topmost = cx.expansion_cause();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
 
     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])
                   -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "column!");
 
-    let topmost = cx.original_span_in_file();
+    let topmost = cx.expansion_cause();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
 
     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])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "file!");
 
-    let topmost = cx.original_span_in_file();
+    let topmost = cx.expansion_cause();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
     let filename = token::intern_and_get_ident(&loc.file.name);
     base::MacEager::expr(cx.expr_str(topmost, filename))