Skip to content

Commit

Permalink
Add illegal_floating_point_literal_pattern compat lint
Browse files Browse the repository at this point in the history
Adds a compatibility lint to disallow floating point literals in
patterns like in match.

See the tracking issue #41620.
  • Loading branch information
est31 committed May 2, 2017
1 parent ed1f26d commit de7dda7
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,82 @@ impl EarlyLintPass for DeprecatedAttr {
}
}

declare_lint! {
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
Warn,
"floating-point literals cannot be used in patterns"
}

/// Checks for floating point literals in patterns.
#[derive(Clone)]
pub struct IllegalFloatLiteralPattern;

impl LintPass for IllegalFloatLiteralPattern {
fn get_lints(&self) -> LintArray {
lint_array!(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN)
}
}

fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
use self::ast::{ExprKind, LitKind};
match expr.node {
ExprKind::Lit(ref l) => {
match l.node {
LitKind::FloatUnsuffixed(..) |
LitKind::Float(..) => {
cx.span_lint(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
l.span,
"floating-point literals cannot be used in patterns");

This comment has been minimized.

Copy link
@alexbool

alexbool May 10, 2017

Contributor

Is this intentional to leave this line?

This comment has been minimized.

Copy link
@est31

est31 May 10, 2017

Author Member

Oops, no, it isn't. Thanks for finding it! #41889

error!("span mc spanspam");
},
_ => (),
}
}
// 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),
}
}

impl EarlyLintPass for IllegalFloatLiteralPattern {
fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
use self::ast::PatKind;
pat.walk(&mut |p| {
match p.node {
// Wildcard patterns and paths are uninteresting for the lint
PatKind::Wild |
PatKind::Path(..) => (),

// The walk logic recurses inside these
PatKind::Ident(..) |
PatKind::Struct(..) |
PatKind::Tuple(..) |
PatKind::TupleStruct(..) |
PatKind::Ref(..) |
PatKind::Box(..) |
PatKind::Slice(..) => (),

// Extract the expressions and check them
PatKind::Lit(ref e) => fl_lit_check_expr(cx, e),
PatKind::Range(ref st, ref en, _) => {
fl_lit_check_expr(cx, st);
fl_lit_check_expr(cx, en);
},

PatKind::Mac(_) => bug!("lint must run post-expansion"),
}
true
});
}
}

declare_lint! {
pub UNCONDITIONAL_RECURSION,
Warn,
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnusedParens,
UnusedImportBraces,
AnonymousParameters,
IllegalFloatLiteralPattern,
);

add_early_builtin_with_new!(sess,
Expand Down Expand Up @@ -201,6 +202,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN),
reference: "issue #36890 <https://github.com/rust-lang/rust/issues/36890>",
},
FutureIncompatibleInfo {
id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
},
FutureIncompatibleInfo {
id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
reference: "issue #36891 <https://github.com/rust-lang/rust/issues/36891>",
Expand Down
51 changes: 51 additions & 0 deletions src/test/compile-fail/issue-41255.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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.

// Matching against float literals should result in a linter error

#![feature(slice_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(unused)]
#![forbid(illegal_floating_point_literal_pattern)]

fn main() {
let x = 42.0;
match x {
5.0 => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
5.0f32 => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
-5.0 => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
//~| ERROR floating-point literals cannot be used
//~| WARNING hard error
39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
//~| ERROR floating-point literals cannot be used
//~| WARNING hard error
_ => {},
};
let y = 5.0;
// Same for tuples
match (x, 5) {
(3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
_ => {},
}
// Or structs
struct Foo { x: f32 };
match (Foo { x }) {
Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
//~| WARNING hard error
_ => {},
}
}

0 comments on commit de7dda7

Please sign in to comment.