mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 22:13:27 +00:00
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.
This commit is contained in:
parent
adbce60d6f
commit
a2adb7db68
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
23
src/test/compile-fail/issue-43250.rs
Normal file
23
src/test/compile-fail/issue-43250.rs
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user