about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-14 05:05:06 +0000
committerbors <bors@rust-lang.org>2017-08-14 05:05:06 +0000
commitbae4fafdfb756690ee31ac939299380cc559c697 (patch)
tree632fc358ce11beca22144a43a08fa54bd4994d7a
parente3245948445b77c25cd9f3b29cbad3187aee3eb7 (diff)
parenta2adb7db6861a7e3bab1d3f11b33a5935984d366 (diff)
downloadrust-bae4fafdfb756690ee31ac939299380cc559c697.tar.gz
rust-bae4fafdfb756690ee31ac939299380cc559c697.zip
Auto merge of #43844 - arielb1:literally-nonstandard, r=eddyb
ast_validation: forbid "nonstandard" literal patterns

Since #42886, macros can create "nonstandard" PatKind::Lit patterns,
that contain path expressions instead of the usual literal expr. These
can cause trouble, including ICEs.

We *could* map these nonstandard patterns to PatKind::Path patterns
during HIR lowering, but that would be much effort for little gain, and
I think is too risky for beta. So let's just forbid them during AST
validation.

Fixes #43250.

beta-nominating because regression.
r? @eddyb
-rw-r--r--src/librustc_passes/ast_validation.rs27
-rw-r--r--src/test/compile-fail/issue-43250.rs23
2 files changed, 44 insertions, 6 deletions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 2643ed2a3c0..b22f8112d7a 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -94,10 +94,25 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
-    fn check_expr_within_pat(&self, expr: &Expr) {
+    /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus),
+    /// or path for ranges.
+    ///
+    /// FIXME: do we want to allow expr -> pattern conversion to create path expressions?
+    /// That means making this work:
+    ///
+    /// ```rust,ignore (FIXME)
+    ///     struct S;
+    ///     macro_rules! m {
+    ///         ($a:expr) => {
+    ///             let $a = S;
+    ///         }
+    ///     }
+    ///     m!(S);
+    /// ```
+    fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
         match expr.node {
-            ExprKind::Lit(..) | ExprKind::Path(..) => {}
+            ExprKind::Lit(..) => {}
+            ExprKind::Path(..) if allow_paths => {}
             ExprKind::Unary(UnOp::Neg, ref inner)
                 if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
             _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
@@ -332,11 +347,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.node {
             PatKind::Lit(ref expr) => {
-                self.check_expr_within_pat(expr);
+                self.check_expr_within_pat(expr, false);
             }
             PatKind::Range(ref start, ref end, _) => {
-                self.check_expr_within_pat(start);
-                self.check_expr_within_pat(end);
+                self.check_expr_within_pat(start, true);
+                self.check_expr_within_pat(end, true);
             }
             _ => {}
         }
diff --git a/src/test/compile-fail/issue-43250.rs b/src/test/compile-fail/issue-43250.rs
new file mode 100644
index 00000000000..e1d34f339dc
--- /dev/null
+++ b/src/test/compile-fail/issue-43250.rs
@@ -0,0 +1,23 @@
+// 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.
+
+fn main() {
+    let mut y;
+    const C: u32 = 0;
+    macro_rules! m {
+        ($a:expr) => {
+            let $a = 0;
+        }
+    }
+    m!(y);
+    //~^ ERROR arbitrary expressions aren't allowed in patterns
+    m!(C);
+    //~^ ERROR arbitrary expressions aren't allowed in patterns
+}