syntax: allow negative integer literal expression to be interpolated as pattern
This commit is contained in:
parent
229d0d3266
commit
0dfd9c30f2
5 changed files with 103 additions and 8 deletions
src
librustc_lint
librustc_passes
libsyntax/parse
test
|
@ -684,13 +684,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
|
|||
// These may occur in patterns
|
||||
// and can maybe contain float literals
|
||||
ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
|
||||
// These may occur in patterns
|
||||
// and can't contain float literals
|
||||
ExprKind::Path(..) => (),
|
||||
// If something unhandled is encountered, we need to expand the
|
||||
// search or ignore more ExprKinds.
|
||||
_ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
|
||||
expr.node),
|
||||
// Other kinds of exprs can't occur in patterns so we don't have to check them
|
||||
// (ast_validation will emit an error if they occur)
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,17 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
|
||||
fn check_expr_within_pat(&self, expr: &Expr) {
|
||||
match expr.node {
|
||||
ExprKind::Lit(..) | ExprKind::Path(..) => {}
|
||||
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 \
|
||||
in patterns")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
|
@ -308,6 +319,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
visit::walk_generics(self, g)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'a Pat) {
|
||||
match pat.node {
|
||||
PatKind::Lit(ref expr) => {
|
||||
self.check_expr_within_pat(expr);
|
||||
}
|
||||
PatKind::Range(ref start, ref end, _) => {
|
||||
self.check_expr_within_pat(start);
|
||||
self.check_expr_within_pat(end);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
visit::walk_pat(self, pat)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(session: &Session, krate: &Crate) {
|
||||
|
|
|
@ -1659,8 +1659,10 @@ impl<'a> Parser<'a> {
|
|||
Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) })
|
||||
}
|
||||
|
||||
/// matches '-' lit | lit
|
||||
/// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat)
|
||||
pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
|
||||
maybe_whole_expr!(self);
|
||||
|
||||
let minus_lo = self.span;
|
||||
let minus_present = self.eat(&token::BinOp(token::Minus));
|
||||
let lo = self.span;
|
||||
|
|
36
src/test/compile-fail/patkind-litrange-no-expr.rs
Normal file
36
src/test/compile-fail/patkind-litrange-no-expr.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
// 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.
|
||||
|
||||
macro_rules! enum_number {
|
||||
($name:ident { $($variant:ident = $value:expr, )* }) => {
|
||||
enum $name {
|
||||
$($variant = $value,)*
|
||||
}
|
||||
|
||||
fn foo(value: i32) -> Option<$name> {
|
||||
match value {
|
||||
$( $value => Some($name::$variant), )* // PatKind::Lit
|
||||
$( $value ... 42 => Some($name::$variant), )* // PatKind::Range
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum_number!(Change {
|
||||
Pos = 1,
|
||||
Neg = -1,
|
||||
Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
|
||||
//~^ ERROR arbitrary expressions aren't allowed in patterns
|
||||
//~^^ ERROR only char and numeric types are allowed in range patterns
|
||||
});
|
||||
|
||||
fn main() {}
|
||||
|
35
src/test/run-pass/macro-pat-neg-lit.rs
Normal file
35
src/test/run-pass/macro-pat-neg-lit.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
// 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.
|
||||
|
||||
macro_rules! enum_number {
|
||||
($name:ident { $($variant:ident = $value:expr, )* }) => {
|
||||
enum $name {
|
||||
$($variant = $value,)*
|
||||
}
|
||||
|
||||
fn foo(value: i32) -> Option<$name> {
|
||||
match value {
|
||||
$( $value => Some($name::$variant), )*
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum_number!(Change {
|
||||
Down = -1,
|
||||
None = 0,
|
||||
Up = 1,
|
||||
});
|
||||
|
||||
fn main() {
|
||||
if let Some(Change::Down) = foo(-1) {} else { panic!() }
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue