Use interpolated token span when building spans for bigger expressions
This commit is contained in:
parent
20edb366e7
commit
1bde18d60c
6 changed files with 42 additions and 39 deletions
|
@ -10,13 +10,12 @@
|
||||||
use self::LockstepIterSize::*;
|
use self::LockstepIterSize::*;
|
||||||
|
|
||||||
use ast;
|
use ast;
|
||||||
use ptr;
|
|
||||||
use ast::{TokenTree, Ident, Name};
|
use ast::{TokenTree, Ident, Name};
|
||||||
use codemap::{Span, DUMMY_SP};
|
use codemap::{Span, DUMMY_SP};
|
||||||
use errors::Handler;
|
use errors::Handler;
|
||||||
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
|
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
|
||||||
use parse::token::{DocComment, MatchNt, SubstNt};
|
use parse::token::{DocComment, MatchNt, SubstNt};
|
||||||
use parse::token::{Token, NtIdent, NtExpr, SpecialMacroVar};
|
use parse::token::{Token, NtIdent, SpecialMacroVar};
|
||||||
use parse::token;
|
use parse::token;
|
||||||
use parse::lexer::TokenAndSpan;
|
use parse::lexer::TokenAndSpan;
|
||||||
|
|
||||||
|
@ -174,11 +173,6 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_span(base: Span, expr: &mut ast::Expr) {
|
|
||||||
expr.span.lo = base.lo;
|
|
||||||
expr.span.hi = base.hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the next token from the TtReader.
|
/// Return the next token from the TtReader.
|
||||||
/// EFFECT: advances the reader's token field
|
/// EFFECT: advances the reader's token field
|
||||||
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||||
|
@ -285,7 +279,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||||
}
|
}
|
||||||
// FIXME #2887: think about span stuff here
|
// FIXME #2887: think about span stuff here
|
||||||
TokenTree::Token(sp, SubstNt(ident, namep)) => {
|
TokenTree::Token(sp, SubstNt(ident, namep)) => {
|
||||||
//println!("SubstNt {:?} {:?}", ident, sp);
|
|
||||||
r.stack.last_mut().unwrap().idx += 1;
|
r.stack.last_mut().unwrap().idx += 1;
|
||||||
match lookup_cur_matched(r, ident) {
|
match lookup_cur_matched(r, ident) {
|
||||||
None => {
|
None => {
|
||||||
|
@ -304,14 +297,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
|
||||||
r.cur_tok = token::Ident(sn.node, b);
|
r.cur_tok = token::Ident(sn.node, b);
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
MatchedNonterminal(NtExpr(ref expr)) => {
|
|
||||||
let mut expr = (**expr).clone();
|
|
||||||
//update_span(sp, &mut expr);
|
|
||||||
// FIXME(pcwalton): Bad copy.
|
|
||||||
r.cur_span = sp;
|
|
||||||
r.cur_tok = token::Interpolated(NtExpr(ptr::P(expr)));
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
MatchedNonterminal(ref other_whole_nt) => {
|
MatchedNonterminal(ref other_whole_nt) => {
|
||||||
// FIXME(pcwalton): Bad copy.
|
// FIXME(pcwalton): Bad copy.
|
||||||
r.cur_span = sp;
|
r.cur_span = sp;
|
||||||
|
|
|
@ -928,6 +928,7 @@ impl<'a> Parser<'a> {
|
||||||
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
|
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
|
||||||
self.last_token = if self.token.is_ident() ||
|
self.last_token = if self.token.is_ident() ||
|
||||||
self.token.is_path() ||
|
self.token.is_path() ||
|
||||||
|
self.token.is_interpolated() ||
|
||||||
self.token == token::Comma {
|
self.token == token::Comma {
|
||||||
Some(Box::new(self.token.clone()))
|
Some(Box::new(self.token.clone()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -2322,13 +2323,9 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
|
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
|
||||||
|
|
||||||
let interp = if let token::Interpolated(..) = self.token {
|
let is_interpolated = self.token.is_interpolated();
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
let b = try!(self.parse_bottom_expr());
|
let b = try!(self.parse_bottom_expr());
|
||||||
let lo = if interp {
|
let lo = if is_interpolated {
|
||||||
self.last_span.lo
|
self.last_span.lo
|
||||||
} else {
|
} else {
|
||||||
b.span.lo
|
b.span.lo
|
||||||
|
@ -2719,27 +2716,31 @@ impl<'a> Parser<'a> {
|
||||||
let ex = match self.token {
|
let ex = match self.token {
|
||||||
token::Not => {
|
token::Not => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
let (interpolated, prev_span) = (self.token.is_interpolated(), self.span);
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = try!(self.parse_prefix_expr(None));
|
||||||
hi = e.span.hi;
|
hi = if interpolated { prev_span.hi } else { e.span.hi };
|
||||||
self.mk_unary(UnNot, e)
|
self.mk_unary(UnNot, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::Minus) => {
|
token::BinOp(token::Minus) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
let (interpolated, prev_span) = (self.token.is_interpolated(), self.span);
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = try!(self.parse_prefix_expr(None));
|
||||||
hi = e.span.hi;
|
hi = if interpolated { prev_span.hi } else { e.span.hi };
|
||||||
self.mk_unary(UnNeg, e)
|
self.mk_unary(UnNeg, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::Star) => {
|
token::BinOp(token::Star) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
let (interpolated, prev_span) = (self.token.is_interpolated(), self.span);
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = try!(self.parse_prefix_expr(None));
|
||||||
hi = e.span.hi;
|
hi = if interpolated { prev_span.hi } else { e.span.hi };
|
||||||
self.mk_unary(UnDeref, e)
|
self.mk_unary(UnDeref, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::And) | token::AndAnd => {
|
token::BinOp(token::And) | token::AndAnd => {
|
||||||
try!(self.expect_and());
|
try!(self.expect_and());
|
||||||
let m = try!(self.parse_mutability());
|
let m = try!(self.parse_mutability());
|
||||||
|
let (interpolated, prev_span) = (self.token.is_interpolated(), self.span);
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = try!(self.parse_prefix_expr(None));
|
||||||
hi = e.span.hi;
|
hi = if interpolated { prev_span.hi } else { e.span.hi };
|
||||||
ExprAddrOf(m, e)
|
ExprAddrOf(m, e)
|
||||||
}
|
}
|
||||||
token::Ident(..) if self.token.is_keyword(keywords::In) => {
|
token::Ident(..) if self.token.is_keyword(keywords::In) => {
|
||||||
|
@ -2757,8 +2758,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
|
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
let (interpolated, prev_span) = (self.token.is_interpolated(), self.span);
|
||||||
let subexpression = try!(self.parse_prefix_expr(None));
|
let subexpression = try!(self.parse_prefix_expr(None));
|
||||||
hi = subexpression.span.hi;
|
hi = if interpolated { prev_span.hi } else { subexpression.span.hi };
|
||||||
ExprBox(subexpression)
|
ExprBox(subexpression)
|
||||||
}
|
}
|
||||||
_ => return self.parse_dot_or_call_expr(Some(attrs))
|
_ => return self.parse_dot_or_call_expr(Some(attrs))
|
||||||
|
@ -2794,12 +2796,20 @@ impl<'a> Parser<'a> {
|
||||||
try!(self.parse_prefix_expr(attrs))
|
try!(self.parse_prefix_expr(attrs))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if self.expr_is_complete(&*lhs) {
|
if self.expr_is_complete(&*lhs) {
|
||||||
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
|
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
|
||||||
return Ok(lhs);
|
return Ok(lhs);
|
||||||
}
|
}
|
||||||
self.expected_tokens.push(TokenType::Operator);
|
self.expected_tokens.push(TokenType::Operator);
|
||||||
while let Some(op) = AssocOp::from_token(&self.token) {
|
while let Some(op) = AssocOp::from_token(&self.token) {
|
||||||
|
|
||||||
|
let lhs_span = match self.last_token {
|
||||||
|
Some(ref lt) if lt.is_interpolated() => self.last_span,
|
||||||
|
_ => lhs.span
|
||||||
|
};
|
||||||
|
|
||||||
let cur_op_span = self.span;
|
let cur_op_span = self.span;
|
||||||
let restrictions = if op.is_assign_like() {
|
let restrictions = if op.is_assign_like() {
|
||||||
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
|
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
|
||||||
|
@ -2815,13 +2825,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
// Special cases:
|
// Special cases:
|
||||||
if op == AssocOp::As {
|
if op == AssocOp::As {
|
||||||
let rhs = try!(self.parse_ty());
|
let rhs = try!(self.parse_ty());
|
||||||
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
|
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
|
||||||
ExprCast(lhs, rhs), None);
|
ExprCast(lhs, rhs), None);
|
||||||
continue
|
continue
|
||||||
} else if op == AssocOp::Colon {
|
} else if op == AssocOp::Colon {
|
||||||
let rhs = try!(self.parse_ty());
|
let rhs = try!(self.parse_ty());
|
||||||
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
|
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
|
||||||
ExprType(lhs, rhs), None);
|
ExprType(lhs, rhs), None);
|
||||||
continue
|
continue
|
||||||
} else if op == AssocOp::DotDot {
|
} else if op == AssocOp::DotDot {
|
||||||
|
@ -2843,7 +2853,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs {
|
let (lhs_span, rhs_span) = (lhs_span, if let Some(ref x) = rhs {
|
||||||
x.span
|
x.span
|
||||||
} else {
|
} else {
|
||||||
cur_op_span
|
cur_op_span
|
||||||
|
@ -2883,14 +2893,14 @@ impl<'a> Parser<'a> {
|
||||||
AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
|
AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
|
||||||
AssocOp::Greater | AssocOp::GreaterEqual => {
|
AssocOp::Greater | AssocOp::GreaterEqual => {
|
||||||
let ast_op = op.to_ast_binop().unwrap();
|
let ast_op = op.to_ast_binop().unwrap();
|
||||||
let (lhs_span, rhs_span) = (lhs.span, rhs.span);
|
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
|
||||||
let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
|
let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
|
||||||
self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
|
self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
|
||||||
}
|
}
|
||||||
AssocOp::Assign =>
|
AssocOp::Assign =>
|
||||||
self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs), None),
|
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprAssign(lhs, rhs), None),
|
||||||
AssocOp::Inplace =>
|
AssocOp::Inplace =>
|
||||||
self.mk_expr(lhs.span.lo, rhs.span.hi, ExprInPlace(lhs, rhs), None),
|
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprInPlace(lhs, rhs), None),
|
||||||
AssocOp::AssignOp(k) => {
|
AssocOp::AssignOp(k) => {
|
||||||
let aop = match k {
|
let aop = match k {
|
||||||
token::Plus => BiAdd,
|
token::Plus => BiAdd,
|
||||||
|
@ -2904,7 +2914,7 @@ impl<'a> Parser<'a> {
|
||||||
token::Shl => BiShl,
|
token::Shl => BiShl,
|
||||||
token::Shr => BiShr
|
token::Shr => BiShr
|
||||||
};
|
};
|
||||||
let (lhs_span, rhs_span) = (lhs.span, rhs.span);
|
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
|
||||||
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
||||||
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
|
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,6 +223,14 @@ impl Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the token is interpolated.
|
||||||
|
pub fn is_interpolated(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Interpolated(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the token is an interpolated path.
|
/// Returns `true` if the token is an interpolated path.
|
||||||
pub fn is_path(&self) -> bool {
|
pub fn is_path(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -19,5 +19,5 @@ fn main() {
|
||||||
foo!(a);
|
foo!(a);
|
||||||
|
|
||||||
foo!(1i32.foo());
|
foo!(1i32.foo());
|
||||||
//~^ ERROR attempted access of field `i32` on type `_`, but no field with that name was found
|
//~^ ERROR no method named `foo` found for type `i32` in the current scope
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,5 @@ macro_rules! not_an_lvalue {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
0 = 42;
|
|
||||||
not_an_lvalue!(99);
|
not_an_lvalue!(99);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// this error is dispayed in `<std macros>`
|
||||||
|
// error-pattern:cannot apply unary operator `!` to type `&'static str`
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert!("foo");
|
assert!("foo");
|
||||||
//~^ ERROR cannot apply unary operator `!` to type `&'static str`
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue