Skip to content

Commit

Permalink
Auto merge of #43844 - arielb1:literally-nonstandard, r=eddyb
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Aug 14, 2017
2 parents e324594 + a2adb7d commit bae4faf
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
27 changes: 21 additions & 6 deletions src/librustc_passes/ast_validation.rs
Expand Up @@ -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 \
Expand Down Expand Up @@ -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);
}
_ => {}
}
Expand Down
23 changes: 23 additions & 0 deletions 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
}

0 comments on commit bae4faf

Please sign in to comment.