Skip to content

Commit 6e4a616

Browse files
committed
remove 'illegal_floating_point_literal_pattern' future-compat lint
1 parent bf98263 commit 6e4a616

35 files changed

+215
-469
lines changed

compiler/rustc_lint/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ fn register_builtins(store: &mut LintStore) {
505505
"replaced with another group of lints, see RFC \
506506
<https://rust-lang.github.io/rfcs/2145-type-privacy.html> for more information",
507507
);
508+
store.register_removed(
509+
"illegal_floating_point_literal_pattern",
510+
"no longer a warning, float patterns behave the same as `==`",
511+
);
508512
}
509513

510514
fn register_internals(store: &mut LintStore) {

compiler/rustc_lint/src/types.rs

+4-24
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_middle::ty::GenericArgsRef;
2121
use rustc_middle::ty::{
2222
self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
2323
};
24+
use rustc_session::lint::builtin;
2425
use rustc_span::def_id::LocalDefId;
2526
use rustc_span::source_map;
2627
use rustc_span::symbol::sym;
@@ -114,35 +115,14 @@ declare_lint! {
114115
"detects enums with widely varying variant sizes"
115116
}
116117

117-
declare_lint! {
118-
/// The `invalid_nan_comparisons` lint checks comparison with `f32::NAN` or `f64::NAN`
119-
/// as one of the operand.
120-
///
121-
/// ### Example
122-
///
123-
/// ```rust
124-
/// let a = 2.3f32;
125-
/// if a == f32::NAN {}
126-
/// ```
127-
///
128-
/// {{produces}}
129-
///
130-
/// ### Explanation
131-
///
132-
/// NaN does not compare meaningfully to anything – not
133-
/// even itself – so those comparisons are always false.
134-
INVALID_NAN_COMPARISONS,
135-
Warn,
136-
"detects invalid floating point NaN comparisons"
137-
}
138-
139118
#[derive(Copy, Clone)]
140119
pub struct TypeLimits {
141120
/// Id of the last visited negated expression
142121
negated_expr_id: Option<hir::HirId>,
143122
}
144123

145-
impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS, INVALID_NAN_COMPARISONS]);
124+
// This pass also emits `INVALID_NAN_COMPARISONS` but adding that to the list here leads to ICEs.
125+
impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS]);
146126

147127
impl TypeLimits {
148128
pub fn new() -> TypeLimits {
@@ -615,7 +595,7 @@ fn lint_nan<'tcx>(
615595
_ => return,
616596
};
617597

618-
cx.emit_spanned_lint(INVALID_NAN_COMPARISONS, e.span, lint);
598+
cx.emit_spanned_lint(builtin::INVALID_NAN_COMPARISONS, e.span, lint);
619599
}
620600

621601
impl<'tcx> LateLintPass<'tcx> for TypeLimits {

compiler/rustc_lint_defs/src/builtin.rs

+26-50
Original file line numberDiff line numberDiff line change
@@ -1754,55 +1754,6 @@ declare_lint! {
17541754
};
17551755
}
17561756

1757-
declare_lint! {
1758-
/// The `illegal_floating_point_literal_pattern` lint detects
1759-
/// floating-point literals used in patterns.
1760-
///
1761-
/// ### Example
1762-
///
1763-
/// ```rust
1764-
/// let x = 42.0;
1765-
///
1766-
/// match x {
1767-
/// 5.0 => {}
1768-
/// _ => {}
1769-
/// }
1770-
/// ```
1771-
///
1772-
/// {{produces}}
1773-
///
1774-
/// ### Explanation
1775-
///
1776-
/// Previous versions of the compiler accepted floating-point literals in
1777-
/// patterns, but it was later determined this was a mistake. The
1778-
/// semantics of comparing floating-point values may not be clear in a
1779-
/// pattern when contrasted with "structural equality". Typically you can
1780-
/// work around this by using a [match guard], such as:
1781-
///
1782-
/// ```rust
1783-
/// # let x = 42.0;
1784-
///
1785-
/// match x {
1786-
/// y if y == 5.0 => {}
1787-
/// _ => {}
1788-
/// }
1789-
/// ```
1790-
///
1791-
/// This is a [future-incompatible] lint to transition this to a hard
1792-
/// error in the future. See [issue #41620] for more details.
1793-
///
1794-
/// [issue #41620]: https://github.com/rust-lang/rust/issues/41620
1795-
/// [match guard]: https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards
1796-
/// [future-incompatible]: ../index.md#future-incompatible-lints
1797-
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
1798-
Warn,
1799-
"floating-point literals cannot be used in patterns",
1800-
@future_incompatible = FutureIncompatibleInfo {
1801-
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
1802-
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
1803-
};
1804-
}
1805-
18061757
declare_lint! {
18071758
/// The `unstable_name_collisions` lint detects that you have used a name
18081759
/// that the standard library plans to add in the future.
@@ -3334,6 +3285,31 @@ declare_lint! {
33343285
"name introduced by a private item shadows a name introduced by a public glob re-export",
33353286
}
33363287

3288+
declare_lint! {
3289+
/// The `invalid_nan_comparisons` lint checks comparison with `f32::NAN` or `f64::NAN`
3290+
/// as one of the operand.
3291+
///
3292+
/// ### Example
3293+
///
3294+
/// ```rust
3295+
/// let a = 2.3f32;
3296+
/// if a == f32::NAN {}
3297+
/// if matches!(a, f32::NAN) {}
3298+
/// ```
3299+
///
3300+
/// {{produces}}
3301+
///
3302+
/// ### Explanation
3303+
///
3304+
/// NaN does not compare meaningfully to anything – not
3305+
/// even itself – so those comparisons are always false.
3306+
pub INVALID_NAN_COMPARISONS,
3307+
Warn,
3308+
"detects invalid floating point NaN comparisons"
3309+
}
3310+
3311+
// When removing any lint here, remember to add a call to `register_removed` in `fn
3312+
// register_builtins` in the `rustc_lints` crate.
33373313
declare_lint_pass! {
33383314
/// Does nothing as a lint pass, but registers some `Lint`s
33393315
/// that are used by other parts of the compiler.
@@ -3371,7 +3347,6 @@ declare_lint_pass! {
33713347
FUZZY_PROVENANCE_CASTS,
33723348
HIDDEN_GLOB_REEXPORTS,
33733349
ILL_FORMED_ATTRIBUTE_INPUT,
3374-
ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
33753350
IMPLIED_BOUNDS_ENTAILMENT,
33763351
INCOMPLETE_INCLUDE,
33773352
INDIRECT_STRUCTURAL_MATCH,
@@ -3380,6 +3355,7 @@ declare_lint_pass! {
33803355
INVALID_ALIGNMENT,
33813356
INVALID_DOC_ATTRIBUTES,
33823357
INVALID_MACRO_EXPORT_ARGUMENTS,
3358+
INVALID_NAN_COMPARISONS,
33833359
INVALID_TYPE_PARAM_DEFAULT,
33843360
IRREFUTABLE_LET_PATTERNS,
33853361
LARGE_ASSIGNMENTS,

compiler/rustc_mir_build/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
8787
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
8888
.label = use of extern static
8989
90-
mir_build_float_pattern = floating-point types cannot be used in patterns
91-
9290
mir_build_indirect_structural_match =
9391
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
9492
@@ -212,6 +210,8 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
212210
.note = mutating layout constrained fields cannot statically be checked for valid values
213211
.label = mutation of layout constrained field
214212
213+
mir_build_nan_pattern = incorrect NaN comparison, NaN cannot be directly compared to itself
214+
215215
mir_build_non_const_path = runtime values cannot be referenced in patterns
216216
217217
mir_build_non_exhaustive_match_all_arms_guarded =

compiler/rustc_mir_build/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -725,8 +725,8 @@ pub struct UnsizedPattern<'tcx> {
725725
}
726726

727727
#[derive(LintDiagnostic)]
728-
#[diag(mir_build_float_pattern)]
729-
pub struct FloatPattern;
728+
#[diag(mir_build_nan_pattern)]
729+
pub struct NaNPattern;
730730

731731
#[derive(LintDiagnostic)]
732732
#[diag(mir_build_pointer_pattern)]

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::cell::Cell;
1616

1717
use super::PatCtxt;
1818
use crate::errors::{
19-
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
20-
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
19+
IndirectStructuralMatch, InvalidPattern, NaNPattern, NontrivialStructuralMatch, PointerPattern,
20+
TypeNotStructural, UnionPattern, UnsizedPattern,
2121
};
2222

2323
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
@@ -291,16 +291,6 @@ impl<'tcx> ConstToPat<'tcx> {
291291
let param_env = self.param_env;
292292

293293
let kind = match ty.kind() {
294-
ty::Float(_) => {
295-
self.saw_const_match_lint.set(true);
296-
tcx.emit_spanned_lint(
297-
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
298-
id,
299-
span,
300-
FloatPattern,
301-
);
302-
return Err(FallbackToConstRef);
303-
}
304294
// If the type is not structurally comparable, just emit the constant directly,
305295
// causing the pattern match code to treat it opaquely.
306296
// FIXME: This code doesn't emit errors itself, the caller emits the errors.
@@ -445,6 +435,25 @@ impl<'tcx> ConstToPat<'tcx> {
445435
}
446436
}
447437
},
438+
ty::Float(fty) => {
439+
// FIXME: Can this be done in a separate lint pass, rather than in the middle of
440+
// const-to-pat conversion?
441+
let val = cv.unwrap_leaf();
442+
let is_nan = match fty {
443+
// FIXME: Do this without host floats.
444+
ty::FloatTy::F32 => f32::from_bits(val.try_to_u32().unwrap()).is_nan(),
445+
ty::FloatTy::F64 => f64::from_bits(val.try_to_u64().unwrap()).is_nan(),
446+
};
447+
if is_nan {
448+
tcx.emit_spanned_lint(
449+
lint::builtin::INVALID_NAN_COMPARISONS,
450+
id,
451+
span,
452+
NaNPattern,
453+
);
454+
}
455+
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
456+
}
448457
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => {
449458
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
450459
}

src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@ mod rustc_ok {
2020
pub fn rustc_lints() {
2121
let x = 42.0;
2222

23-
#[expect(illegal_floating_point_literal_pattern)]
24-
match x {
25-
5.0 => {}
26-
6.0 => {}
27-
_ => {}
28-
}
23+
#[expect(invalid_nan_comparisons)]
24+
let _b = x == f32::NAN;
2925
}
3026
}
3127

@@ -38,13 +34,9 @@ mod rustc_warn {
3834
pub fn rustc_lints() {
3935
let x = 42;
4036

41-
#[expect(illegal_floating_point_literal_pattern)]
37+
#[expect(invalid_nan_comparisons)]
4238
//~^ ERROR: this lint expectation is unfulfilled
43-
match x {
44-
5 => {}
45-
6 => {}
46-
_ => {}
47-
}
39+
let _b = x == 5;
4840
}
4941
}
5042

src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this lint expectation is unfulfilled
2-
--> $DIR/expect_tool_lint_rfc_2383.rs:35:14
2+
--> $DIR/expect_tool_lint_rfc_2383.rs:31:14
33
|
44
LL | #[expect(dead_code)]
55
| ^^^^^^^^^
@@ -8,31 +8,31 @@ LL | #[expect(dead_code)]
88
= help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]`
99

1010
error: this lint expectation is unfulfilled
11-
--> $DIR/expect_tool_lint_rfc_2383.rs:41:18
11+
--> $DIR/expect_tool_lint_rfc_2383.rs:37:18
1212
|
13-
LL | #[expect(illegal_floating_point_literal_pattern)]
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
LL | #[expect(invalid_nan_comparisons)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^
1515

1616
error: this lint expectation is unfulfilled
17-
--> $DIR/expect_tool_lint_rfc_2383.rs:116:14
17+
--> $DIR/expect_tool_lint_rfc_2383.rs:108:14
1818
|
1919
LL | #[expect(clippy::almost_swapped)]
2020
| ^^^^^^^^^^^^^^^^^^^^^^
2121

2222
error: this lint expectation is unfulfilled
23-
--> $DIR/expect_tool_lint_rfc_2383.rs:124:14
23+
--> $DIR/expect_tool_lint_rfc_2383.rs:116:14
2424
|
2525
LL | #[expect(clippy::bytes_nth)]
2626
| ^^^^^^^^^^^^^^^^^
2727

2828
error: this lint expectation is unfulfilled
29-
--> $DIR/expect_tool_lint_rfc_2383.rs:130:14
29+
--> $DIR/expect_tool_lint_rfc_2383.rs:122:14
3030
|
3131
LL | #[expect(clippy::if_same_then_else)]
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^
3333

3434
error: this lint expectation is unfulfilled
35-
--> $DIR/expect_tool_lint_rfc_2383.rs:136:14
35+
--> $DIR/expect_tool_lint_rfc_2383.rs:128:14
3636
|
3737
LL | #[expect(clippy::overly_complex_bool_expr)]
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ mod rustc_ok {
2424
pub fn rustc_lints() {
2525
let x = 42.0;
2626

27-
#[expect(illegal_floating_point_literal_pattern)]
27+
#[expect(invalid_nan_comparisons)]
2828
match x {
29-
5.0 => {}
30-
6.0 => {}
29+
f32::NAN => {}
3130
_ => {}
3231
}
3332
}
@@ -40,7 +39,7 @@ mod rustc_warn {
4039
pub fn rustc_lints() {
4140
let x = 42;
4241

43-
#[expect(illegal_floating_point_literal_pattern)]
42+
#[expect(invalid_nan_comparisons)]
4443
match x {
4544
5 => {}
4645
6 => {}

tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ LL | #![expect(rustdoc::missing_crate_level_docs)]
77
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
88

99
warning: this lint expectation is unfulfilled
10-
--> $DIR/expect-tool-lint-rfc-2383.rs:71:14
10+
--> $DIR/expect-tool-lint-rfc-2383.rs:70:14
1111
|
1212
LL | #[expect(rustdoc::broken_intra_doc_links)]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: this lint expectation is unfulfilled
16-
--> $DIR/expect-tool-lint-rfc-2383.rs:76:14
16+
--> $DIR/expect-tool-lint-rfc-2383.rs:75:14
1717
|
1818
LL | #[expect(rustdoc::invalid_html_tags)]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
2020

2121
warning: this lint expectation is unfulfilled
22-
--> $DIR/expect-tool-lint-rfc-2383.rs:81:14
22+
--> $DIR/expect-tool-lint-rfc-2383.rs:80:14
2323
|
2424
LL | #[expect(rustdoc::bare_urls)]
2525
| ^^^^^^^^^^^^^^^^^^

tests/ui/array-slice-vec/vec-matching-autoslice.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
32

43
pub fn main() {
54
let x = [1, 2, 3];

tests/ui/binding/match-range.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
32
#![feature(exclusive_range_pattern)]
43

54
pub fn main() {

tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
22

33
#![feature(exclusive_range_pattern)]
4-
#![allow(illegal_floating_point_literal_pattern)]
54

65
fn main() {}
76

0 commit comments

Comments
 (0)