about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-04 17:04:34 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-07 11:21:57 +0300
commit5fa1c1b5f3e03a8f2049c6a36f58fae1fe05852d (patch)
treece6a673749a2eba6d0605dc1ed7410ee85fdd6ac
parent24fc541e7cee966ad8752eb8360f0d4e9ba0bef0 (diff)
downloadrust-5fa1c1b5f3e03a8f2049c6a36f58fae1fe05852d.tar.gz
rust-5fa1c1b5f3e03a8f2049c6a36f58fae1fe05852d.zip
Fix spans for binary operator expression with interpolated identifiers
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/test/ui/issue-42954.rs20
-rw-r--r--src/test/ui/issue-42954.stderr13
3 files changed, 45 insertions, 5 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 23d85232369..f35ecbe20e0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -150,13 +150,14 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
     lhs
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Copy, PartialEq)]
 enum PrevTokenKind {
     DocComment,
     Comma,
     Plus,
     Interpolated,
     Eof,
+    Ident,
     Other,
 }
 
@@ -1040,6 +1041,7 @@ impl<'a> Parser<'a> {
             token::BinOp(token::Plus) => PrevTokenKind::Plus,
             token::Interpolated(..) => PrevTokenKind::Interpolated,
             token::Eof => PrevTokenKind::Eof,
+            token::Ident(..) => PrevTokenKind::Ident,
             _ => PrevTokenKind::Other,
         };
 
@@ -2777,10 +2779,15 @@ impl<'a> Parser<'a> {
         self.expected_tokens.push(TokenType::Operator);
         while let Some(op) = AssocOp::from_token(&self.token) {
 
-            let lhs_span = if self.prev_token_kind == PrevTokenKind::Interpolated {
-                self.prev_span
-            } else {
-                lhs.span
+            // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what
+            // it refers to. Interpolated identifiers are unwrapped early and never show up here
+            // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process
+            // it as "interpolated", it doesn't change the answer for non-interpolated idents.
+            let lhs_span = match (self.prev_token_kind, &lhs.node) {
+                (PrevTokenKind::Interpolated, _) => self.prev_span,
+                (PrevTokenKind::Ident, &ExprKind::Path(None, ref path))
+                    if path.segments.len() == 1 => self.prev_span,
+                _ => lhs.span,
             };
 
             let cur_op_span = self.span;
diff --git a/src/test/ui/issue-42954.rs b/src/test/ui/issue-42954.rs
new file mode 100644
index 00000000000..ee0367b8a68
--- /dev/null
+++ b/src/test/ui/issue-42954.rs
@@ -0,0 +1,20 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! is_plainly_printable {
+    ($i: ident) => {
+      $i as u32 < 0
+    };
+}
+
+fn main() {
+    let c = 'a';
+    is_plainly_printable!(c);
+}
diff --git a/src/test/ui/issue-42954.stderr b/src/test/ui/issue-42954.stderr
new file mode 100644
index 00000000000..0ac3d82c719
--- /dev/null
+++ b/src/test/ui/issue-42954.stderr
@@ -0,0 +1,13 @@
+error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
+  --> $DIR/issue-42954.rs:13:19
+   |
+13 |       $i as u32 < 0
+   |                 - ^ interpreted as generic argument
+   |                 |
+   |                 not interpreted as comparison
+   |
+help: if you want to compare the casted value then write:
+   |       ($i as u32) < 0
+
+error: aborting due to previous error
+