Skip to content

Commit de7dda7

Browse files
committed
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.
1 parent ed1f26d commit de7dda7

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

src/librustc_lint/builtin.rs

+76
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,82 @@ impl EarlyLintPass for DeprecatedAttr {
692692
}
693693
}
694694

695+
declare_lint! {
696+
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
697+
Warn,
698+
"floating-point literals cannot be used in patterns"
699+
}
700+
701+
/// Checks for floating point literals in patterns.
702+
#[derive(Clone)]
703+
pub struct IllegalFloatLiteralPattern;
704+
705+
impl LintPass for IllegalFloatLiteralPattern {
706+
fn get_lints(&self) -> LintArray {
707+
lint_array!(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN)
708+
}
709+
}
710+
711+
fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
712+
use self::ast::{ExprKind, LitKind};
713+
match expr.node {
714+
ExprKind::Lit(ref l) => {
715+
match l.node {
716+
LitKind::FloatUnsuffixed(..) |
717+
LitKind::Float(..) => {
718+
cx.span_lint(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
719+
l.span,
720+
"floating-point literals cannot be used in patterns");
721+
error!("span mc spanspam");
722+
},
723+
_ => (),
724+
}
725+
}
726+
// These may occur in patterns
727+
// and can maybe contain float literals
728+
ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
729+
// These may occur in patterns
730+
// and can't contain float literals
731+
ExprKind::Path(..) => (),
732+
// If something unhandled is encountered, we need to expand the
733+
// search or ignore more ExprKinds.
734+
_ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
735+
expr.node),
736+
}
737+
}
738+
739+
impl EarlyLintPass for IllegalFloatLiteralPattern {
740+
fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
741+
use self::ast::PatKind;
742+
pat.walk(&mut |p| {
743+
match p.node {
744+
// Wildcard patterns and paths are uninteresting for the lint
745+
PatKind::Wild |
746+
PatKind::Path(..) => (),
747+
748+
// The walk logic recurses inside these
749+
PatKind::Ident(..) |
750+
PatKind::Struct(..) |
751+
PatKind::Tuple(..) |
752+
PatKind::TupleStruct(..) |
753+
PatKind::Ref(..) |
754+
PatKind::Box(..) |
755+
PatKind::Slice(..) => (),
756+
757+
// Extract the expressions and check them
758+
PatKind::Lit(ref e) => fl_lit_check_expr(cx, e),
759+
PatKind::Range(ref st, ref en, _) => {
760+
fl_lit_check_expr(cx, st);
761+
fl_lit_check_expr(cx, en);
762+
},
763+
764+
PatKind::Mac(_) => bug!("lint must run post-expansion"),
765+
}
766+
true
767+
});
768+
}
769+
}
770+
695771
declare_lint! {
696772
pub UNCONDITIONAL_RECURSION,
697773
Warn,

src/librustc_lint/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
113113
UnusedParens,
114114
UnusedImportBraces,
115115
AnonymousParameters,
116+
IllegalFloatLiteralPattern,
116117
);
117118

118119
add_early_builtin_with_new!(sess,
@@ -201,6 +202,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
201202
id: LintId::of(ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN),
202203
reference: "issue #36890 <https://github.com/rust-lang/rust/issues/36890>",
203204
},
205+
FutureIncompatibleInfo {
206+
id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
207+
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
208+
},
204209
FutureIncompatibleInfo {
205210
id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
206211
reference: "issue #36891 <https://github.com/rust-lang/rust/issues/36891>",

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

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
// Matching against float literals should result in a linter error
12+
13+
#![feature(slice_patterns)]
14+
#![feature(exclusive_range_pattern)]
15+
#![allow(unused)]
16+
#![forbid(illegal_floating_point_literal_pattern)]
17+
18+
fn main() {
19+
let x = 42.0;
20+
match x {
21+
5.0 => {}, //~ ERROR floating-point literals cannot be used
22+
//~| WARNING hard error
23+
5.0f32 => {}, //~ ERROR floating-point literals cannot be used
24+
//~| WARNING hard error
25+
-5.0 => {}, //~ ERROR floating-point literals cannot be used
26+
//~| WARNING hard error
27+
1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
28+
//~| WARNING hard error
29+
//~| ERROR floating-point literals cannot be used
30+
//~| WARNING hard error
31+
39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
32+
//~| WARNING hard error
33+
//~| ERROR floating-point literals cannot be used
34+
//~| WARNING hard error
35+
_ => {},
36+
};
37+
let y = 5.0;
38+
// Same for tuples
39+
match (x, 5) {
40+
(3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
41+
//~| WARNING hard error
42+
_ => {},
43+
}
44+
// Or structs
45+
struct Foo { x: f32 };
46+
match (Foo { x }) {
47+
Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
48+
//~| WARNING hard error
49+
_ => {},
50+
}
51+
}

0 commit comments

Comments
 (0)