Skip to content

Commit 5bb0cac

Browse files
arielb1alexcrichton
authored andcommitted
ast_validation: forbid "nonstandard" literal patterns
Since rust-lang#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 rust-lang#43250.
1 parent f0cd695 commit 5bb0cac

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

src/librustc_passes/ast_validation.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,25 @@ impl<'a> AstValidator<'a> {
9494
}
9595
}
9696

97-
/// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
98-
fn check_expr_within_pat(&self, expr: &Expr) {
97+
/// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus),
98+
/// or path for ranges.
99+
///
100+
/// FIXME: do we want to allow expr -> pattern conversion to create path expressions?
101+
/// That means making this work:
102+
///
103+
/// ```rust,ignore (FIXME)
104+
/// struct S;
105+
/// macro_rules! m {
106+
/// ($a:expr) => {
107+
/// let $a = S;
108+
/// }
109+
/// }
110+
/// m!(S);
111+
/// ```
112+
fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
99113
match expr.node {
100-
ExprKind::Lit(..) | ExprKind::Path(..) => {}
114+
ExprKind::Lit(..) => {}
115+
ExprKind::Path(..) if allow_paths => {}
101116
ExprKind::Unary(UnOp::Neg, ref inner)
102117
if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
103118
_ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
@@ -340,11 +355,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
340355
fn visit_pat(&mut self, pat: &'a Pat) {
341356
match pat.node {
342357
PatKind::Lit(ref expr) => {
343-
self.check_expr_within_pat(expr);
358+
self.check_expr_within_pat(expr, false);
344359
}
345360
PatKind::Range(ref start, ref end, _) => {
346-
self.check_expr_within_pat(start);
347-
self.check_expr_within_pat(end);
361+
self.check_expr_within_pat(start, true);
362+
self.check_expr_within_pat(end, true);
348363
}
349364
_ => {}
350365
}

src/test/compile-fail/issue-43250.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
let mut y;
13+
const C: u32 = 0;
14+
macro_rules! m {
15+
($a:expr) => {
16+
let $a = 0;
17+
}
18+
}
19+
m!(y);
20+
//~^ ERROR arbitrary expressions aren't allowed in patterns
21+
m!(C);
22+
//~^ ERROR arbitrary expressions aren't allowed in patterns
23+
}

0 commit comments

Comments
 (0)