From 1bde18d60c2e2a4fec149312bae6e20609b6599b Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 24 Jan 2016 22:46:39 +0100 Subject: [PATCH] Use interpolated token span when building spans for bigger expressions --- src/libsyntax/ext/tt/transcribe.rs | 17 +--------- src/libsyntax/parse/parser.rs | 48 +++++++++++++++++----------- src/libsyntax/parse/token.rs | 8 +++++ src/test/compile-fail/issue-25385.rs | 2 +- src/test/compile-fail/issue-26093.rs | 2 -- src/test/compile-fail/issue-28308.rs | 4 ++- 6 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 6cf05558adb55..8878c606d6a2c 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -10,13 +10,12 @@ use self::LockstepIterSize::*; use ast; -use ptr; use ast::{TokenTree, Ident, Name}; use codemap::{Span, DUMMY_SP}; use errors::Handler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{DocComment, MatchNt, SubstNt}; -use parse::token::{Token, NtIdent, NtExpr, SpecialMacroVar}; +use parse::token::{Token, NtIdent, SpecialMacroVar}; use parse::token; 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. /// EFFECT: advances the reader's token field 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 TokenTree::Token(sp, SubstNt(ident, namep)) => { - //println!("SubstNt {:?} {:?}", ident, sp); r.stack.last_mut().unwrap().idx += 1; match lookup_cur_matched(r, ident) { None => { @@ -304,14 +297,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.cur_tok = token::Ident(sn.node, b); 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) => { // FIXME(pcwalton): Bad copy. r.cur_span = sp; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f5ebe842577c6..6b41900282845 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -928,6 +928,7 @@ impl<'a> Parser<'a> { // Stash token for error recovery (sometimes; clone is not necessarily cheap). self.last_token = if self.token.is_ident() || self.token.is_path() || + self.token.is_interpolated() || self.token == token::Comma { Some(Box::new(self.token.clone())) } else { @@ -2322,13 +2323,9 @@ impl<'a> Parser<'a> { -> PResult<'a, P> { let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs)); - let interp = if let token::Interpolated(..) = self.token { - true - } else { - false - }; + let is_interpolated = self.token.is_interpolated(); let b = try!(self.parse_bottom_expr()); - let lo = if interp { + let lo = if is_interpolated { self.last_span.lo } else { b.span.lo @@ -2719,27 +2716,31 @@ impl<'a> Parser<'a> { let ex = match self.token { token::Not => { self.bump(); + let (interpolated, prev_span) = (self.token.is_interpolated(), self.span); 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) } token::BinOp(token::Minus) => { self.bump(); + let (interpolated, prev_span) = (self.token.is_interpolated(), self.span); 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) } token::BinOp(token::Star) => { self.bump(); + let (interpolated, prev_span) = (self.token.is_interpolated(), self.span); 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) } token::BinOp(token::And) | token::AndAnd => { try!(self.expect_and()); let m = try!(self.parse_mutability()); + let (interpolated, prev_span) = (self.token.is_interpolated(), self.span); 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) } 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) => { self.bump(); + let (interpolated, prev_span) = (self.token.is_interpolated(), self.span); let subexpression = try!(self.parse_prefix_expr(None)); - hi = subexpression.span.hi; + hi = if interpolated { prev_span.hi } else { subexpression.span.hi }; ExprBox(subexpression) } _ => return self.parse_dot_or_call_expr(Some(attrs)) @@ -2794,12 +2796,20 @@ impl<'a> Parser<'a> { try!(self.parse_prefix_expr(attrs)) } }; + + if self.expr_is_complete(&*lhs) { // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } self.expected_tokens.push(TokenType::Operator); 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 restrictions = if op.is_assign_like() { self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL @@ -2815,13 +2825,13 @@ impl<'a> Parser<'a> { } // Special cases: if op == AssocOp::As { - let rhs = try!(self.parse_ty()); - lhs = self.mk_expr(lhs.span.lo, rhs.span.hi, + let rhs = try!(self.parse_ty()); + lhs = self.mk_expr(lhs_span.lo, rhs.span.hi, ExprCast(lhs, rhs), None); continue } else if op == AssocOp::Colon { 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); continue } else if op == AssocOp::DotDot { @@ -2843,7 +2853,7 @@ impl<'a> Parser<'a> { } else { 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 } else { cur_op_span @@ -2883,14 +2893,14 @@ impl<'a> Parser<'a> { AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual | AssocOp::Greater | AssocOp::GreaterEqual => { 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); self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None) } 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 => - 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) => { let aop = match k { token::Plus => BiAdd, @@ -2904,7 +2914,7 @@ impl<'a> Parser<'a> { token::Shl => BiShl, 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); self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 242626154fc8c..220d0aff2e3af 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -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. pub fn is_path(&self) -> bool { match *self { diff --git a/src/test/compile-fail/issue-25385.rs b/src/test/compile-fail/issue-25385.rs index 3ee6cdedf0c04..aa941bc569130 100644 --- a/src/test/compile-fail/issue-25385.rs +++ b/src/test/compile-fail/issue-25385.rs @@ -19,5 +19,5 @@ fn main() { foo!(a); 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 } diff --git a/src/test/compile-fail/issue-26093.rs b/src/test/compile-fail/issue-26093.rs index 6ac36707505a4..3489a2ca9be15 100644 --- a/src/test/compile-fail/issue-26093.rs +++ b/src/test/compile-fail/issue-26093.rs @@ -16,7 +16,5 @@ macro_rules! not_an_lvalue { } fn main() { - - 0 = 42; not_an_lvalue!(99); } diff --git a/src/test/compile-fail/issue-28308.rs b/src/test/compile-fail/issue-28308.rs index 43261a97f7b15..642bb0c4a107e 100644 --- a/src/test/compile-fail/issue-28308.rs +++ b/src/test/compile-fail/issue-28308.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// this error is dispayed in `` +// error-pattern:cannot apply unary operator `!` to type `&'static str` + fn main() { assert!("foo"); - //~^ ERROR cannot apply unary operator `!` to type `&'static str` }