diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2017-08-13 16:59:54 +0300 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2017-08-23 07:45:08 -0700 |
| commit | 5bb0cac84891de785ce803ca2bd36a55cd9775d9 (patch) | |
| tree | 9a4177820f594f382e1ff2e4352ff1878c3a515f | |
| parent | f0cd69592b49821f2f1a1b9f5cf5416ef120b6a9 (diff) | |
| download | rust-5bb0cac84891de785ce803ca2bd36a55cd9775d9.tar.gz rust-5bb0cac84891de785ce803ca2bd36a55cd9775d9.zip | |
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.
| -rw-r--r-- | src/librustc_passes/ast_validation.rs | 27 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-43250.rs | 23 |
2 files changed, 44 insertions, 6 deletions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 72c7b92fe6e..66736507abc 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 \ @@ -340,11 +355,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 +} |
