about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2018-08-31 20:35:03 +0200
committerDavid Wood <david@davidtw.co>2018-09-02 10:54:28 +0200
commit8c92cbe90e5453c684b6cbc71377af84758ea01e (patch)
tree57525ff272b970b5b7308f0f8f5ed0f2b7cd1c74
parent2ce56c5ebf4b63c274da678c367a4d85a13994a8 (diff)
downloadrust-8c92cbe90e5453c684b6cbc71377af84758ea01e.tar.gz
rust-8c92cbe90e5453c684b6cbc71377af84758ea01e.zip
Moved let-chain warning/error to ast_validation and changed to unconditional error.
-rw-r--r--src/librustc_passes/ast_validation.rs48
-rw-r--r--src/libsyntax/parse/parser.rs53
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs13
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr50
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr24
5 files changed, 92 insertions, 96 deletions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index bca119660aa..3981d9f0c64 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -22,6 +22,7 @@ use syntax::ast::*;
 use syntax::attr;
 use syntax::source_map::Spanned;
 use syntax::symbol::keywords;
+use syntax::ptr::P;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
 use errors;
@@ -167,11 +168,58 @@ impl<'a> AstValidator<'a> {
                 "only lifetime parameters can be used in this context");
         }
     }
+
+    /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
+    /// depending on the edition, this function handles that.
+    fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
+        if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) {
+            let mut err = self.err_handler().struct_span_err(
+                span, &format!("ambigious use of `{}`", op_kind.to_string())
+            );
+
+            err.note(
+                "this will be a error until the `let_chains` feature is stabilized"
+            );
+
+            if let Ok(snippet) = self.session.source_map().span_to_snippet(span) {
+                err.span_suggestion(
+                    span, "consider adding parentheses", format!("({})", snippet),
+                );
+            }
+
+            err.emit();
+        }
+    }
+
+    /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
+    /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
+    /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
+    /// that the current expression parsed is ambigious and will break in future.
+    fn while_if_let_expr_ambiguity(&self, expr: &P<Expr>) -> Option<(Span, BinOpKind)> {
+        debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node);
+        match &expr.node {
+            ExprKind::Binary(op, _, _) if op.node == BinOpKind::And || op.node == BinOpKind::Or => {
+                Some((expr.span, op.node))
+            },
+            ExprKind::Range(ref lhs, ref rhs, _) => {
+                let lhs_ambigious = lhs.as_ref()
+                    .and_then(|lhs| self.while_if_let_expr_ambiguity(lhs));
+                let rhs_ambigious = rhs.as_ref()
+                    .and_then(|rhs| self.while_if_let_expr_ambiguity(rhs));
+
+                lhs_ambigious.or(rhs_ambigious)
+            }
+            _ => None,
+        }
+    }
+
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_expr(&mut self, expr: &'a Expr) {
         match expr.node {
+            ExprKind::IfLet(_, ref expr, _, _) | ExprKind::WhileLet(_, ref expr, _, _) =>
+                self.while_if_let_ambiguity(&expr),
             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
                 span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
             }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f0e6dfb8775..1695d3a8f96 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3327,8 +3327,6 @@ impl<'a> Parser<'a> {
         let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
-        self.while_if_let_ambiguity(&expr);
-
         let thn = self.parse_block()?;
         let (hi, els) = if self.eat_keyword(keywords::Else) {
             let expr = self.parse_else_expr()?;
@@ -3339,56 +3337,6 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs))
     }
 
-    /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
-    /// depending on the edition, this function handles that.
-    fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
-        if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) {
-            let message = format!("ambigious use of `{}`", op_kind.to_string());
-            let mut err = if self.span.edition() >= Edition::Edition2018 {
-                self.diagnostic().struct_span_err(span, &message)
-            } else {
-                self.diagnostic().struct_span_warn(span, &message)
-            };
-
-            let note = if self.span.edition() >= Edition::Edition2018 {
-                "This will be a error until the `let_chains` feature is stabilized."
-            } else {
-                "This will be a error in Rust 2018 until the `let_chains` feature is stabilized."
-            };
-            err.note(note);
-
-            if let Ok(snippet) = self.sess.source_map().span_to_snippet(span) {
-                err.span_suggestion(
-                    span, "consider adding parenthesis", format!("({})", snippet),
-                );
-            }
-
-            err.emit();
-        }
-    }
-
-    /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
-    /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
-    /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
-    /// that the current expression parsed is ambigious and will break in future.
-    fn while_if_let_expr_ambiguity(&self, expr: &P<Expr>) -> Option<(Span, BinOpKind)> {
-        debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node);
-        match &expr.node {
-            ExprKind::Binary(op, _, _) if op.node == BinOpKind::And || op.node == BinOpKind::Or => {
-                Some((expr.span, op.node))
-            },
-            ExprKind::Range(ref lhs, ref rhs, _) => {
-                let lhs_ambigious = lhs.as_ref()
-                    .and_then(|lhs| self.while_if_let_expr_ambiguity(lhs));
-                let rhs_ambigious = rhs.as_ref()
-                    .and_then(|rhs| self.while_if_let_expr_ambiguity(rhs));
-
-                lhs_ambigious.or(rhs_ambigious)
-            }
-            _ => None,
-        }
-    }
-
     // `move |args| expr`
     fn parse_lambda_expr(&mut self,
                              attrs: ThinVec<Attribute>)
@@ -3489,7 +3437,6 @@ impl<'a> Parser<'a> {
         let pats = self.parse_pats()?;
         self.expect(&token::Eq)?;
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
-        self.while_if_let_ambiguity(&expr);
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         let span = span_lo.to(body.span);
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs
index 06ce23eda7d..339d49104b0 100644
--- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // edition:2015
-// compile-pass
 
 // Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
 // with examples easier.
@@ -20,22 +19,22 @@ fn main() {
     use std::ops::Range;
 
     if let Range { start: _, end: _ } = true..true && false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `&&`
 
     if let Range { start: _, end: _ } = true..true || false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `||`
 
     while let Range { start: _, end: _ } = true..true && false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `&&`
 
     while let Range { start: _, end: _ } = true..true || false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `||`
 
     if let true = false && false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `&&`
 
     while let true = (1 == 2) && false { }
-    //~^ WARN error in 2018
+    //~^ ERROR ambigious use of `&&`
 
     // The following cases are not an error as parenthesis are used to
     // clarify intent:
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr
index a4c3be62ec4..0e6ccb5d9d8 100644
--- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr
@@ -1,48 +1,50 @@
-warning: ambigious use of `&&`
-  --> $DIR/syntax-ambiguity-2015.rs:22:47
+error: ambigious use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:21:47
    |
 LL |     if let Range { start: _, end: _ } = true..true && false { }
-   |                                               ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
-warning: ambigious use of `||`
-  --> $DIR/syntax-ambiguity-2015.rs:25:47
+error: ambigious use of `||`
+  --> $DIR/syntax-ambiguity-2015.rs:24:47
    |
 LL |     if let Range { start: _, end: _ } = true..true || false { }
-   |                                               ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
-warning: ambigious use of `&&`
-  --> $DIR/syntax-ambiguity-2015.rs:28:50
+error: ambigious use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:27:50
    |
 LL |     while let Range { start: _, end: _ } = true..true && false { }
-   |                                                  ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
-warning: ambigious use of `||`
-  --> $DIR/syntax-ambiguity-2015.rs:31:50
+error: ambigious use of `||`
+  --> $DIR/syntax-ambiguity-2015.rs:30:50
    |
 LL |     while let Range { start: _, end: _ } = true..true || false { }
-   |                                                  ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
-warning: ambigious use of `&&`
-  --> $DIR/syntax-ambiguity-2015.rs:34:19
+error: ambigious use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:33:19
    |
 LL |     if let true = false && false { }
-   |                   ^^^^^^^^^^^^^^ help: consider adding parenthesis: `(false && false)`
+   |                   ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
-warning: ambigious use of `&&`
-  --> $DIR/syntax-ambiguity-2015.rs:37:22
+error: ambigious use of `&&`
+  --> $DIR/syntax-ambiguity-2015.rs:36:22
    |
 LL |     while let true = (1 == 2) && false { }
-   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parenthesis: `((1 == 2) && false)`
+   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
    |
-   = note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr
index c472a8904bf..2bbeda360d7 100644
--- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr
@@ -2,49 +2,49 @@ error: ambigious use of `&&`
   --> $DIR/syntax-ambiguity-2018.rs:21:47
    |
 LL |     if let Range { start: _, end: _ } = true..true && false { }
-   |                                               ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: ambigious use of `||`
   --> $DIR/syntax-ambiguity-2018.rs:24:47
    |
 LL |     if let Range { start: _, end: _ } = true..true || false { }
-   |                                               ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
+   |                                               ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: ambigious use of `&&`
   --> $DIR/syntax-ambiguity-2018.rs:27:50
    |
 LL |     while let Range { start: _, end: _ } = true..true && false { }
-   |                                                  ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: ambigious use of `||`
   --> $DIR/syntax-ambiguity-2018.rs:30:50
    |
 LL |     while let Range { start: _, end: _ } = true..true || false { }
-   |                                                  ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
+   |                                                  ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: ambigious use of `&&`
   --> $DIR/syntax-ambiguity-2018.rs:33:19
    |
 LL |     if let true = false && false { }
-   |                   ^^^^^^^^^^^^^^ help: consider adding parenthesis: `(false && false)`
+   |                   ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: ambigious use of `&&`
   --> $DIR/syntax-ambiguity-2018.rs:36:22
    |
 LL |     while let true = (1 == 2) && false { }
-   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parenthesis: `((1 == 2) && false)`
+   |                      ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
    |
-   = note: This will be a error until the `let_chains` feature is stabilized.
+   = note: this will be a error until the `let_chains` feature is stabilized
 
 error: aborting due to 6 previous errors