Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ed27148

Browse files
authoredFeb 5, 2024
Rollup merge of #116284 - RalfJung:no-nan-match, r=cjgillot
make matching on NaN a hard error, and remove the rest of illegal_floating_point_literal_pattern These arms would never be hit anyway, so the pattern makes little sense. We have had a future-compat lint against float matches in general for a *long* time, so I hope we can get away with immediately making this a hard error. This is part of implementing rust-lang/rfcs#3535. Closes #41620 by removing the lint. rust-lang/reference#1456 updates the reference to match.
2 parents fd8ea25 + 9f14fc4 commit ed27148

35 files changed

+349
-486
lines changed
 

‎compiler/rustc_lint/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,10 @@ fn register_builtins(store: &mut LintStore) {
516516
"converted into hard error, see PR #118649 \
517517
<https://github.com/rust-lang/rust/pull/118649> for more information",
518518
);
519+
store.register_removed(
520+
"illegal_floating_point_literal_pattern",
521+
"no longer a warning, float patterns behave the same as `==`",
522+
);
519523
}
520524

521525
fn register_internals(store: &mut LintStore) {

‎compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ declare_lint_pass! {
4545
FUZZY_PROVENANCE_CASTS,
4646
HIDDEN_GLOB_REEXPORTS,
4747
ILL_FORMED_ATTRIBUTE_INPUT,
48-
ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
4948
INCOMPLETE_INCLUDE,
5049
INDIRECT_STRUCTURAL_MATCH,
5150
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
@@ -1873,55 +1872,6 @@ declare_lint! {
18731872
};
18741873
}
18751874

1876-
declare_lint! {
1877-
/// The `illegal_floating_point_literal_pattern` lint detects
1878-
/// floating-point literals used in patterns.
1879-
///
1880-
/// ### Example
1881-
///
1882-
/// ```rust
1883-
/// let x = 42.0;
1884-
///
1885-
/// match x {
1886-
/// 5.0 => {}
1887-
/// _ => {}
1888-
/// }
1889-
/// ```
1890-
///
1891-
/// {{produces}}
1892-
///
1893-
/// ### Explanation
1894-
///
1895-
/// Previous versions of the compiler accepted floating-point literals in
1896-
/// patterns, but it was later determined this was a mistake. The
1897-
/// semantics of comparing floating-point values may not be clear in a
1898-
/// pattern when contrasted with "structural equality". Typically you can
1899-
/// work around this by using a [match guard], such as:
1900-
///
1901-
/// ```rust
1902-
/// # let x = 42.0;
1903-
///
1904-
/// match x {
1905-
/// y if y == 5.0 => {}
1906-
/// _ => {}
1907-
/// }
1908-
/// ```
1909-
///
1910-
/// This is a [future-incompatible] lint to transition this to a hard
1911-
/// error in the future. See [issue #41620] for more details.
1912-
///
1913-
/// [issue #41620]: https://github.com/rust-lang/rust/issues/41620
1914-
/// [match guard]: https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards
1915-
/// [future-incompatible]: ../index.md#future-incompatible-lints
1916-
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
1917-
Warn,
1918-
"floating-point literals cannot be used in patterns",
1919-
@future_incompatible = FutureIncompatibleInfo {
1920-
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
1921-
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
1922-
};
1923-
}
1924-
19251875
declare_lint! {
19261876
/// The `unstable_name_collisions` lint detects that you have used a name
19271877
/// that the standard library plans to add in the future.

‎compiler/rustc_middle/src/mir/interpret/value.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,8 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
418418

419419
#[inline]
420420
pub fn to_float<F: Float>(self) -> InterpResult<'tcx, F> {
421-
// Going through `to_uint` to check size and truncation.
422-
Ok(F::from_bits(self.to_uint(Size::from_bits(F::BITS))?))
421+
// Going through `to_bits` to check size and truncation.
422+
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
423423
}
424424

425425
#[inline]

‎compiler/rustc_middle/src/ty/consts/int.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ impl ScalarInt {
249249
}
250250
}
251251

252-
#[inline]
253-
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
254-
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
255-
}
256-
257252
/// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
258253
/// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
259254
/// `ScalarInt`s size in that case.
@@ -262,56 +257,61 @@ impl ScalarInt {
262257
self.to_bits(size)
263258
}
264259

265-
// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
266-
// in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
267-
// value of the `ScalarInt` in that case.
268-
#[inline]
269-
pub fn try_to_bool(self) -> Result<bool, Size> {
270-
match self.try_to_u8()? {
271-
0 => Ok(false),
272-
1 => Ok(true),
273-
_ => Err(self.size()),
274-
}
275-
}
276-
277260
// Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
278261
// in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in
279262
// that case.
280263
#[inline]
281264
pub fn try_to_u8(self) -> Result<u8, Size> {
282-
self.to_bits(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
265+
self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
283266
}
284267

285268
/// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt`
286269
/// in not equal to `Size { raw: 2 }` and returns the `size` value of the `ScalarInt` in
287270
/// that case.
288271
#[inline]
289272
pub fn try_to_u16(self) -> Result<u16, Size> {
290-
self.to_bits(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
273+
self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
291274
}
292275

293276
/// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt`
294277
/// in not equal to `Size { raw: 4 }` and returns the `size` value of the `ScalarInt` in
295278
/// that case.
296279
#[inline]
297280
pub fn try_to_u32(self) -> Result<u32, Size> {
298-
self.to_bits(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
281+
self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
299282
}
300283

301284
/// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt`
302285
/// in not equal to `Size { raw: 8 }` and returns the `size` value of the `ScalarInt` in
303286
/// that case.
304287
#[inline]
305288
pub fn try_to_u64(self) -> Result<u64, Size> {
306-
self.to_bits(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
289+
self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
307290
}
308291

309292
/// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt`
310293
/// in not equal to `Size { raw: 16 }` and returns the `size` value of the `ScalarInt` in
311294
/// that case.
312295
#[inline]
313296
pub fn try_to_u128(self) -> Result<u128, Size> {
314-
self.to_bits(Size::from_bits(128))
297+
self.try_to_uint(Size::from_bits(128))
298+
}
299+
300+
#[inline]
301+
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
302+
self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap())
303+
}
304+
305+
// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
306+
// in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
307+
// value of the `ScalarInt` in that case.
308+
#[inline]
309+
pub fn try_to_bool(self) -> Result<bool, Size> {
310+
match self.try_to_u8()? {
311+
0 => Ok(false),
312+
1 => Ok(true),
313+
_ => Err(self.size()),
314+
}
315315
}
316316

317317
/// Tries to convert the `ScalarInt` to a signed integer of the given size.
@@ -357,6 +357,27 @@ impl ScalarInt {
357357
pub fn try_to_i128(self) -> Result<i128, Size> {
358358
self.try_to_int(Size::from_bits(128))
359359
}
360+
361+
#[inline]
362+
pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result<i64, Size> {
363+
self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap())
364+
}
365+
366+
#[inline]
367+
pub fn try_to_float<F: Float>(self) -> Result<F, Size> {
368+
// Going through `to_uint` to check size and truncation.
369+
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
370+
}
371+
372+
#[inline]
373+
pub fn try_to_f32(self) -> Result<Single, Size> {
374+
self.try_to_float()
375+
}
376+
377+
#[inline]
378+
pub fn try_to_f64(self) -> Result<Double, Size> {
379+
self.try_to_float()
380+
}
360381
}
361382

362383
macro_rules! from {
@@ -399,11 +420,7 @@ impl TryFrom<ScalarInt> for bool {
399420
type Error = Size;
400421
#[inline]
401422
fn try_from(int: ScalarInt) -> Result<Self, Size> {
402-
int.to_bits(Size::from_bytes(1)).and_then(|u| match u {
403-
0 => Ok(false),
404-
1 => Ok(true),
405-
_ => Err(Size::from_bytes(1)),
406-
})
423+
int.try_to_bool()
407424
}
408425
}
409426

‎compiler/rustc_mir_build/messages.ftl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
107107
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
108108
.label = use of extern static
109109
110-
mir_build_float_pattern = floating-point types cannot be used in patterns
111-
112110
mir_build_indirect_structural_match =
113111
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
114112
@@ -232,6 +230,10 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
232230
.note = mutating layout constrained fields cannot statically be checked for valid values
233231
.label = mutation of layout constrained field
234232
233+
mir_build_nan_pattern = cannot use NaN in patterns
234+
.note = NaNs compare inequal to everything, even themselves, so this pattern would never match
235+
.help = try using the `is_nan` method instead
236+
235237
mir_build_non_const_path = runtime values cannot be referenced in patterns
236238
237239
mir_build_non_empty_never_pattern =

‎compiler/rustc_mir_build/src/errors.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -780,9 +780,14 @@ pub struct UnsizedPattern<'tcx> {
780780
pub non_sm_ty: Ty<'tcx>,
781781
}
782782

783-
#[derive(LintDiagnostic)]
784-
#[diag(mir_build_float_pattern)]
785-
pub struct FloatPattern;
783+
#[derive(Diagnostic)]
784+
#[diag(mir_build_nan_pattern)]
785+
#[note]
786+
#[help]
787+
pub struct NaNPattern {
788+
#[primary_span]
789+
pub span: Span,
790+
}
786791

787792
#[derive(LintDiagnostic)]
788793
#[diag(mir_build_pointer_pattern)]

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

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_apfloat::Float;
12
use rustc_hir as hir;
23
use rustc_hir::def_id::DefId;
34
use rustc_index::Idx;
@@ -16,7 +17,7 @@ use std::cell::Cell;
1617

1718
use super::PatCtxt;
1819
use crate::errors::{
19-
FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch,
20+
IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch,
2021
NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
2122
};
2223

@@ -317,16 +318,6 @@ impl<'tcx> ConstToPat<'tcx> {
317318
let param_env = self.param_env;
318319

319320
let kind = match ty.kind() {
320-
ty::Float(_) => {
321-
self.saw_const_match_lint.set(true);
322-
tcx.emit_node_span_lint(
323-
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
324-
id,
325-
span,
326-
FloatPattern,
327-
);
328-
return Err(FallbackToOpaqueConst);
329-
}
330321
// If the type is not structurally comparable, just emit the constant directly,
331322
// causing the pattern match code to treat it opaquely.
332323
// FIXME: This code doesn't emit errors itself, the caller emits the errors.
@@ -486,6 +477,22 @@ impl<'tcx> ConstToPat<'tcx> {
486477
}
487478
}
488479
},
480+
ty::Float(flt) => {
481+
let v = cv.unwrap_leaf();
482+
let is_nan = match flt {
483+
ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(),
484+
ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(),
485+
};
486+
if is_nan {
487+
// NaNs are not ever equal to anything so they make no sense as patterns.
488+
// Also see <https://github.com/rust-lang/rfcs/pull/3535>.
489+
let e = tcx.dcx().emit_err(NaNPattern { span });
490+
self.saw_const_match_error.set(Some(e));
491+
return Err(FallbackToOpaqueConst);
492+
} else {
493+
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
494+
}
495+
}
489496
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
490497
// The raw pointers we see here have been "vetted" by valtree construction to be
491498
// just integers, so we simply allow them.

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

Lines changed: 4 additions & 12 deletions
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

Lines changed: 8 additions & 8 deletions
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

Lines changed: 3 additions & 4 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 0 additions & 1 deletion
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

Lines changed: 0 additions & 1 deletion
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

Lines changed: 0 additions & 1 deletion
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

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

Lines changed: 68 additions & 68 deletions
Large diffs are not rendered by default.

‎tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// via `.contains(...)` and make sure the dynamic semantics match.
55

66
#![feature(exclusive_range_pattern)]
7-
#![allow(illegal_floating_point_literal_pattern)]
87
#![allow(unreachable_patterns)]
98

109
macro_rules! yes {

‎tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![feature(exclusive_range_pattern)]
2-
#![allow(illegal_floating_point_literal_pattern)]
32

43
macro_rules! m {
54
($s:expr, $($t:tt)+) => {

‎tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,77 @@
11
error[E0579]: lower range bound must be less than upper
2-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11
2+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:10:11
33
|
44
LL | m!(0, ..u8::MIN);
55
| ^^^^^^^^^
66

77
error[E0579]: lower range bound must be less than upper
8-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:13:11
8+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
99
|
1010
LL | m!(0, ..u16::MIN);
1111
| ^^^^^^^^^^
1212

1313
error[E0579]: lower range bound must be less than upper
14-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
14+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
1515
|
1616
LL | m!(0, ..u32::MIN);
1717
| ^^^^^^^^^^
1818

1919
error[E0579]: lower range bound must be less than upper
20-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11
20+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:16:11
2121
|
2222
LL | m!(0, ..u64::MIN);
2323
| ^^^^^^^^^^
2424

2525
error[E0579]: lower range bound must be less than upper
26-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11
26+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
2727
|
2828
LL | m!(0, ..u128::MIN);
2929
| ^^^^^^^^^^^
3030

3131
error[E0579]: lower range bound must be less than upper
32-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:22:11
32+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
3333
|
3434
LL | m!(0, ..i8::MIN);
3535
| ^^^^^^^^^
3636

3737
error[E0579]: lower range bound must be less than upper
38-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
38+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
3939
|
4040
LL | m!(0, ..i16::MIN);
4141
| ^^^^^^^^^^
4242

4343
error[E0579]: lower range bound must be less than upper
44-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:26:11
44+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:25:11
4545
|
4646
LL | m!(0, ..i32::MIN);
4747
| ^^^^^^^^^^
4848

4949
error[E0579]: lower range bound must be less than upper
50-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
50+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
5151
|
5252
LL | m!(0, ..i64::MIN);
5353
| ^^^^^^^^^^
5454

5555
error[E0579]: lower range bound must be less than upper
56-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
56+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:29:11
5757
|
5858
LL | m!(0, ..i128::MIN);
5959
| ^^^^^^^^^^^
6060

6161
error[E0579]: lower range bound must be less than upper
62-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14
62+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14
6363
|
6464
LL | m!(0f32, ..f32::NEG_INFINITY);
6565
| ^^^^^^^^^^^^^^^^^^^
6666

6767
error[E0579]: lower range bound must be less than upper
68-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:35:14
68+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:34:14
6969
|
7070
LL | m!(0f64, ..f64::NEG_INFINITY);
7171
| ^^^^^^^^^^^^^^^^^^^
7272

7373
error[E0579]: lower range bound must be less than upper
74-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:38:13
74+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:37:13
7575
|
7676
LL | m!('a', ..'\u{0}');
7777
| ^^^^^^^^^

‎tests/ui/lint/issue-86600-lint-twice.rs

Lines changed: 0 additions & 15 deletions
This file was deleted.

‎tests/ui/lint/issue-86600-lint-twice.stderr

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,8 @@ mod rustc_ok {
2222
pub fn rustc_lints() {
2323
let x = 42.0;
2424

25-
#[expect(illegal_floating_point_literal_pattern)]
26-
match x {
27-
5.0 => {}
28-
6.0 => {}
29-
_ => {}
30-
}
25+
#[expect(invalid_nan_comparisons)]
26+
let _b = x == f32::NAN;
3127
}
3228
}
3329

@@ -40,13 +36,9 @@ mod rustc_warn {
4036
pub fn rustc_lints() {
4137
let x = 42;
4238

43-
#[expect(illegal_floating_point_literal_pattern)]
39+
#[expect(invalid_nan_comparisons)]
4440
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
45-
match x {
46-
5 => {}
47-
6 => {}
48-
_ => {}
49-
}
41+
let _b = x == 5;
5042
}
5143
}
5244

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
warning: this lint expectation is unfulfilled
2-
--> $DIR/expect_tool_lint_rfc_2383.rs:37:14
2+
--> $DIR/expect_tool_lint_rfc_2383.rs:33:14
33
|
44
LL | #[expect(dead_code)]
55
| ^^^^^^^^^
66
|
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:43:18
10+
--> $DIR/expect_tool_lint_rfc_2383.rs:39:18
1111
|
12-
LL | #[expect(illegal_floating_point_literal_pattern)]
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
LL | #[expect(invalid_nan_comparisons)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: 2 warnings emitted
1616

‎tests/ui/match/issue-41255.rs

Lines changed: 0 additions & 50 deletions
This file was deleted.

‎tests/ui/match/issue-41255.stderr

Lines changed: 0 additions & 115 deletions
This file was deleted.

‎tests/ui/match/match-float.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// run-pass
2+
// Makes sure we use `==` (not bitwise) semantics for float comparison.
3+
4+
fn main() {
5+
const F1: f32 = 0.0;
6+
const F2: f32 = -0.0;
7+
assert_eq!(F1, F2);
8+
assert_ne!(F1.to_bits(), F2.to_bits());
9+
assert!(matches!(F1, F2));
10+
assert!(matches!(F2, F1));
11+
}

‎tests/ui/parser/issues/issue-7222.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// run-pass
22
// pretty-expanded FIXME #23616
3-
#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
43

54
pub fn main() {
65
const FOO: f64 = 10.0;

‎tests/ui/pattern/usefulness/floats.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![feature(exclusive_range_pattern)]
2-
#![allow(illegal_floating_point_literal_pattern)]
32
#![deny(unreachable_patterns)]
43

54
fn main() {

‎tests/ui/pattern/usefulness/floats.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0004]: non-exhaustive patterns: `_` not covered
2-
--> $DIR/floats.rs:11:11
2+
--> $DIR/floats.rs:10:11
33
|
44
LL | match 0.0 {
55
| ^^^ pattern `_` not covered
@@ -12,49 +12,49 @@ LL + _ => todo!()
1212
|
1313

1414
error: unreachable pattern
15-
--> $DIR/floats.rs:19:9
15+
--> $DIR/floats.rs:18:9
1616
|
1717
LL | 0.01f64 => {}
1818
| ^^^^^^^
1919
|
2020
note: the lint level is defined here
21-
--> $DIR/floats.rs:3:9
21+
--> $DIR/floats.rs:2:9
2222
|
2323
LL | #![deny(unreachable_patterns)]
2424
| ^^^^^^^^^^^^^^^^^^^^
2525

2626
error: unreachable pattern
27-
--> $DIR/floats.rs:20:9
27+
--> $DIR/floats.rs:19:9
2828
|
2929
LL | 0.02f64 => {}
3030
| ^^^^^^^
3131

3232
error: unreachable pattern
33-
--> $DIR/floats.rs:21:9
33+
--> $DIR/floats.rs:20:9
3434
|
3535
LL | 6.5f64 => {}
3636
| ^^^^^^
3737

3838
error: unreachable pattern
39-
--> $DIR/floats.rs:23:9
39+
--> $DIR/floats.rs:22:9
4040
|
4141
LL | 1.0f64..=4.0f64 => {}
4242
| ^^^^^^^^^^^^^^^
4343

4444
error: unreachable pattern
45-
--> $DIR/floats.rs:35:9
45+
--> $DIR/floats.rs:34:9
4646
|
4747
LL | 0.01f32 => {}
4848
| ^^^^^^^
4949

5050
error: unreachable pattern
51-
--> $DIR/floats.rs:36:9
51+
--> $DIR/floats.rs:35:9
5252
|
5353
LL | 0.02f32 => {}
5454
| ^^^^^^^
5555

5656
error: unreachable pattern
57-
--> $DIR/floats.rs:37:9
57+
--> $DIR/floats.rs:36:9
5858
|
5959
LL | 6.5f32 => {}
6060
| ^^^^^^

‎tests/ui/pattern/usefulness/non-exhaustive-match.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(illegal_floating_point_literal_pattern)]
2-
31
enum T { A, B }
42

53
fn main() {

‎tests/ui/pattern/usefulness/non-exhaustive-match.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0004]: non-exhaustive patterns: `T::A` not covered
2-
--> $DIR/non-exhaustive-match.rs:7:11
2+
--> $DIR/non-exhaustive-match.rs:5:11
33
|
44
LL | match x { T::B => { } }
55
| ^ pattern `T::A` not covered
66
|
77
note: `T` defined here
8-
--> $DIR/non-exhaustive-match.rs:3:6
8+
--> $DIR/non-exhaustive-match.rs:1:6
99
|
1010
LL | enum T { A, B }
1111
| ^ - not covered
@@ -16,7 +16,7 @@ LL | match x { T::B => { }, T::A => todo!() }
1616
| +++++++++++++++++
1717

1818
error[E0004]: non-exhaustive patterns: `false` not covered
19-
--> $DIR/non-exhaustive-match.rs:8:11
19+
--> $DIR/non-exhaustive-match.rs:6:11
2020
|
2121
LL | match true {
2222
| ^^^^ pattern `false` not covered
@@ -29,7 +29,7 @@ LL + false => todo!()
2929
|
3030

3131
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
32-
--> $DIR/non-exhaustive-match.rs:11:11
32+
--> $DIR/non-exhaustive-match.rs:9:11
3333
|
3434
LL | match Some(10) {
3535
| ^^^^^^^^ pattern `Some(_)` not covered
@@ -47,7 +47,7 @@ LL + Some(_) => todo!()
4747
|
4848

4949
error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
50-
--> $DIR/non-exhaustive-match.rs:14:11
50+
--> $DIR/non-exhaustive-match.rs:12:11
5151
|
5252
LL | match (2, 3, 4) {
5353
| ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
@@ -60,7 +60,7 @@ LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!()
6060
|
6161

6262
error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered
63-
--> $DIR/non-exhaustive-match.rs:18:11
63+
--> $DIR/non-exhaustive-match.rs:16:11
6464
|
6565
LL | match (T::A, T::A) {
6666
| ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered
@@ -73,13 +73,13 @@ LL + (T::A, T::A) | (T::B, T::B) => todo!()
7373
|
7474

7575
error[E0004]: non-exhaustive patterns: `T::B` not covered
76-
--> $DIR/non-exhaustive-match.rs:22:11
76+
--> $DIR/non-exhaustive-match.rs:20:11
7777
|
7878
LL | match T::A {
7979
| ^^^^ pattern `T::B` not covered
8080
|
8181
note: `T` defined here
82-
--> $DIR/non-exhaustive-match.rs:3:6
82+
--> $DIR/non-exhaustive-match.rs:1:6
8383
|
8484
LL | enum T { A, B }
8585
| ^ - not covered
@@ -91,7 +91,7 @@ LL + T::B => todo!()
9191
|
9292

9393
error[E0004]: non-exhaustive patterns: `[]` not covered
94-
--> $DIR/non-exhaustive-match.rs:33:11
94+
--> $DIR/non-exhaustive-match.rs:31:11
9595
|
9696
LL | match *vec {
9797
| ^^^^ pattern `[]` not covered
@@ -104,7 +104,7 @@ LL + [] => todo!()
104104
|
105105

106106
error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
107-
--> $DIR/non-exhaustive-match.rs:46:11
107+
--> $DIR/non-exhaustive-match.rs:44:11
108108
|
109109
LL | match *vec {
110110
| ^^^^ pattern `[_, _, _, _, ..]` not covered
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Matching against NaN should result in an error
2+
#![feature(exclusive_range_pattern)]
3+
#![allow(unused)]
4+
5+
const NAN: f64 = f64::NAN;
6+
7+
#[derive(PartialEq, Eq)]
8+
struct MyType<T>(T);
9+
10+
const C: MyType<f32> = MyType(f32::NAN);
11+
12+
fn main() {
13+
let x = NAN;
14+
match x {
15+
NAN => {}, //~ ERROR cannot use NaN in patterns
16+
_ => {},
17+
};
18+
19+
match [x, 1.0] {
20+
[NAN, _] => {}, //~ ERROR cannot use NaN in patterns
21+
_ => {},
22+
};
23+
24+
match MyType(1.0f32) {
25+
C => {}, //~ ERROR cannot use NaN in patterns
26+
_ => {},
27+
}
28+
29+
// Also cover range patterns
30+
match x {
31+
NAN..=1.0 => {}, //~ ERROR cannot use NaN in patterns
32+
//~^ ERROR lower range bound must be less than or equal to upper
33+
-1.0..=NAN => {}, //~ ERROR cannot use NaN in patterns
34+
//~^ ERROR lower range bound must be less than or equal to upper
35+
NAN.. => {}, //~ ERROR cannot use NaN in patterns
36+
//~^ ERROR lower range bound must be less than or equal to upper
37+
..NAN => {}, //~ ERROR cannot use NaN in patterns
38+
//~^ ERROR lower range bound must be less than upper
39+
_ => {},
40+
};
41+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
error: cannot use NaN in patterns
2+
--> $DIR/issue-6804-nan-match.rs:15:9
3+
|
4+
LL | NAN => {},
5+
| ^^^
6+
|
7+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
8+
= help: try using the `is_nan` method instead
9+
10+
error: cannot use NaN in patterns
11+
--> $DIR/issue-6804-nan-match.rs:20:10
12+
|
13+
LL | [NAN, _] => {},
14+
| ^^^
15+
|
16+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
17+
= help: try using the `is_nan` method instead
18+
19+
error: cannot use NaN in patterns
20+
--> $DIR/issue-6804-nan-match.rs:25:9
21+
|
22+
LL | C => {},
23+
| ^
24+
|
25+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
26+
= help: try using the `is_nan` method instead
27+
28+
error: cannot use NaN in patterns
29+
--> $DIR/issue-6804-nan-match.rs:31:9
30+
|
31+
LL | NAN..=1.0 => {},
32+
| ^^^
33+
|
34+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
35+
= help: try using the `is_nan` method instead
36+
37+
error[E0030]: lower range bound must be less than or equal to upper
38+
--> $DIR/issue-6804-nan-match.rs:31:9
39+
|
40+
LL | NAN..=1.0 => {},
41+
| ^^^^^^^^^ lower bound larger than upper bound
42+
43+
error: cannot use NaN in patterns
44+
--> $DIR/issue-6804-nan-match.rs:33:16
45+
|
46+
LL | -1.0..=NAN => {},
47+
| ^^^
48+
|
49+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
50+
= help: try using the `is_nan` method instead
51+
52+
error[E0030]: lower range bound must be less than or equal to upper
53+
--> $DIR/issue-6804-nan-match.rs:33:9
54+
|
55+
LL | -1.0..=NAN => {},
56+
| ^^^^^^^^^^ lower bound larger than upper bound
57+
58+
error: cannot use NaN in patterns
59+
--> $DIR/issue-6804-nan-match.rs:35:9
60+
|
61+
LL | NAN.. => {},
62+
| ^^^
63+
|
64+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
65+
= help: try using the `is_nan` method instead
66+
67+
error[E0030]: lower range bound must be less than or equal to upper
68+
--> $DIR/issue-6804-nan-match.rs:35:9
69+
|
70+
LL | NAN.. => {},
71+
| ^^^^^ lower bound larger than upper bound
72+
73+
error: cannot use NaN in patterns
74+
--> $DIR/issue-6804-nan-match.rs:37:11
75+
|
76+
LL | ..NAN => {},
77+
| ^^^
78+
|
79+
= note: NaNs compare inequal to everything, even themselves, so this pattern would never match
80+
= help: try using the `is_nan` method instead
81+
82+
error[E0579]: lower range bound must be less than upper
83+
--> $DIR/issue-6804-nan-match.rs:37:9
84+
|
85+
LL | ..NAN => {},
86+
| ^^^^^
87+
88+
error: aborting due to 11 previous errors
89+
90+
Some errors have detailed explanations: E0030, E0579.
91+
For more information about an error, try `rustc --explain E0030`.

‎tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

‎tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr

Lines changed: 0 additions & 25 deletions
This file was deleted.

‎tests/ui/union/union-pat-refutability.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// run-pass
22

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

65
#[repr(u32)]
76
enum Tag {

0 commit comments

Comments
 (0)
Please sign in to comment.