From de7dda7bf413dc214e3f1552d6cb3f8052283513 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 29 Apr 2017 09:15:07 +0200 Subject: [PATCH 1/3] Add illegal_floating_point_literal_pattern compat lint Adds a compatibility lint to disallow floating point literals in patterns like in match. See the tracking issue #41620. --- src/librustc_lint/builtin.rs | 76 ++++++++++++++++++++++++++++ src/librustc_lint/lib.rs | 5 ++ src/test/compile-fail/issue-41255.rs | 51 +++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 src/test/compile-fail/issue-41255.rs diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c9ec152841b20..715a769158bc3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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"); + 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, diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c1c14cb1fd29e..53ea3a8333f2d 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -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, @@ -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 ", }, + FutureIncompatibleInfo { + id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN), + reference: "issue #41620 ", + }, FutureIncompatibleInfo { id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN), reference: "issue #36891 ", diff --git a/src/test/compile-fail/issue-41255.rs b/src/test/compile-fail/issue-41255.rs new file mode 100644 index 0000000000000..191b867e7a8b5 --- /dev/null +++ b/src/test/compile-fail/issue-41255.rs @@ -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 or the MIT license +// , 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 + _ => {}, + } +} From 51c3173465ef4e158117da2421707f3b0a9d3e25 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 29 Apr 2017 10:02:42 +0200 Subject: [PATCH 2/3] Fix non exhaustive match test --- src/test/compile-fail/non-exhaustive-match.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/compile-fail/non-exhaustive-match.rs b/src/test/compile-fail/non-exhaustive-match.rs index 74e728d713b1d..13b62429f4693 100644 --- a/src/test/compile-fail/non-exhaustive-match.rs +++ b/src/test/compile-fail/non-exhaustive-match.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(slice_patterns)] +#![allow(illegal_floating_point_literal_pattern)] enum t { a, b, } From 37fb676fcf99631b0acd69585e5b3899485fd96b Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 29 Apr 2017 10:09:02 +0200 Subject: [PATCH 3/3] Fix test --- src/test/compile-fail/issue-41255.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/compile-fail/issue-41255.rs b/src/test/compile-fail/issue-41255.rs index 191b867e7a8b5..a4585f7bac7da 100644 --- a/src/test/compile-fail/issue-41255.rs +++ b/src/test/compile-fail/issue-41255.rs @@ -39,6 +39,8 @@ fn main() { match (x, 5) { (3.14, 1) => {}, //~ ERROR floating-point literals cannot be used //~| WARNING hard error + //~| ERROR floating-point literals cannot be used + //~| WARNING hard error _ => {}, } // Or structs @@ -46,6 +48,8 @@ fn main() { match (Foo { x }) { Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used //~| WARNING hard error + //~| ERROR floating-point literals cannot be used + //~| WARNING hard error _ => {}, } }