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
This commit is contained in:
Simonas Kazlauskas 2015-06-16 21:47:09 +03:00
parent 73fb19c04a
commit 7ff55eaf25
3 changed files with 72 additions and 72 deletions

View file

@ -17,7 +17,7 @@
//! within the CodeMap, which upon request can be converted to line and column
//! information, source code snippets, etc.
pub use self::MacroFormat::*;
pub use self::ExpnFormat::*;
use std::cell::RefCell;
use std::ops::{Add, Sub};
@ -228,17 +228,17 @@ pub struct FileMapAndBytePos { pub fm: Rc<FileMap>, pub pos: BytePos }
// _____________________________________________________________________________
// MacroFormat, NameAndSpan, ExpnInfo, ExpnId
// ExpnFormat, NameAndSpan, ExpnInfo, ExpnId
//
/// The syntax with which a macro was invoked.
#[derive(Clone, Copy, Hash, Debug)]
pub enum MacroFormat {
/// The source of expansion.
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
pub enum ExpnFormat {
/// e.g. #[derive(...)] <item>
MacroAttribute,
/// e.g. `format!()`
MacroBang,
/// Expansion performed by the compiler (libsyntax::expand).
/// Syntax sugar expansion performed by the compiler (libsyntax::expand).
CompilerExpansion,
}
@ -248,7 +248,7 @@ pub struct NameAndSpan {
/// with this Span.
pub name: String,
/// The format with which the macro was invoked.
pub format: MacroFormat,
pub format: ExpnFormat,
/// Whether the macro is allowed to use #[unstable]/feature-gated
/// features internally without forcing the whole crate to opt-in
/// to them.
@ -259,11 +259,11 @@ pub struct NameAndSpan {
pub span: Option<Span>
}
/// Extra information for tracking macro expansion of spans
/// Extra information for tracking spans of macro and syntax sugar expansion
#[derive(Hash, Debug)]
pub struct ExpnInfo {
/// The location of the actual macro invocation, e.g. `let x =
/// foo!();`
/// The location of the actual macro invocation or syntax sugar , e.g.
/// `let x = foo!();` or `if let Some(y) = x {}`
///
/// This may recursively refer to other macro invocations, e.g. if
/// `foo!()` invoked `bar!()` internally, and there was an
@ -272,12 +272,7 @@ pub struct ExpnInfo {
/// call_site span would have its own ExpnInfo, with the call_site
/// pointing to the `foo!` invocation.
pub call_site: Span,
/// Information about the macro and its definition.
///
/// The `callee` of the inner expression in the `call_site`
/// example would point to the `macro_rules! bar { ... }` and that
/// of the `bar!()` invocation would point to the `macro_rules!
/// foo { ... }`.
/// Information about the expansion.
pub callee: NameAndSpan
}
@ -677,7 +672,39 @@ impl CodeMap {
/// Lookup source information about a BytePos
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
self.lookup_pos(pos)
let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
let line = a + 1; // Line numbers start at 1
let chpos = self.bytepos_to_file_charpos(pos);
let linebpos = (*f.lines.borrow())[a];
let linechpos = self.bytepos_to_file_charpos(linebpos);
debug!("byte pos {:?} is on the line at byte pos {:?}",
pos, linebpos);
debug!("char pos {:?} is on the line at char pos {:?}",
chpos, linechpos);
debug!("byte is on line: {}", line);
assert!(chpos >= linechpos);
Loc {
file: f,
line: line,
col: chpos - linechpos
}
}
fn lookup_line(&self, pos: BytePos) -> FileMapAndLine {
let idx = self.lookup_filemap_idx(pos);
let files = self.files.borrow();
let f = (*files)[idx].clone();
let mut a = 0;
{
let lines = f.lines.borrow();
let mut b = lines.len();
while b - a > 1 {
let m = (a + b) / 2;
if (*lines)[m] > pos { b = m; } else { a = m; }
}
}
FileMapAndLine {fm: f, line: a}
}
pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
@ -877,42 +904,6 @@ impl CodeMap {
return a;
}
fn lookup_line(&self, pos: BytePos) -> FileMapAndLine {
let idx = self.lookup_filemap_idx(pos);
let files = self.files.borrow();
let f = (*files)[idx].clone();
let mut a = 0;
{
let lines = f.lines.borrow();
let mut b = lines.len();
while b - a > 1 {
let m = (a + b) / 2;
if (*lines)[m] > pos { b = m; } else { a = m; }
}
}
FileMapAndLine {fm: f, line: a}
}
fn lookup_pos(&self, pos: BytePos) -> Loc {
let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
let line = a + 1; // Line numbers start at 1
let chpos = self.bytepos_to_file_charpos(pos);
let linebpos = (*f.lines.borrow())[a];
let linechpos = self.bytepos_to_file_charpos(linebpos);
debug!("byte pos {:?} is on the line at byte pos {:?}",
pos, linebpos);
debug!("char pos {:?} is on the line at char pos {:?}",
chpos, linechpos);
debug!("byte is on line: {}", line);
assert!(chpos >= linechpos);
Loc {
file: f,
line: line,
col: chpos - linechpos
}
}
pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId {
let mut expansions = self.expansions.borrow_mut();
expansions.push(expn_info);