You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking issue for illegal_floating_point_literal_pattern compatibility lint #41620
This is a tracking issue for the compatibility lint disallowing floating point literals in patterns.
The corresponding RFC is RFC 1445. Originally, #36890 was the only tracking issue for floats in patterns, but after it was found out that the implementation of that lint doesn't cover literals (issue #41255), another lint and tracking issue were required.
The goal of this lint is to make code like this a hard error:
fnmain(){let x = 13.4;match x {1.0 => println!("one"),22.4 => println!("two"),3.67 => println!("three"),13.4 => println!("thirteen point four"),
_ => println!("anything"),}}
No, its separate. There are two separate lints. This one is about literals, the one tracked in that issue is about constants. I have opened the PR #41293 after finding out about #41255.
RFC 1445 is about const constants. Why are float literals restricted as well?
From my perspective, primitive literals (as opposed to destructuring struct literals) are a kind of constant. The same questions raised by consts in that RFC are raised by primitive literals.
From my perspective, primitive literals (as opposed to destructuring struct literals) are a kind of constant.
Given that we have a language keyword named const, I think it is reasonable to assume that constants are cont items and nothing else. If a different definition of the term is intended, it should absolutely be defined explicitly. This is not the case in this RFC.
The example quoted in the tracking issue you linked never was implemented that way. I have asked about whether to create a separate lint or add the check to the existing one, and it was decided to create a separate lint.
I guess the example should be removed from that issue's description.
I would definitely say that the RFC was intended to apply equally to all constants, whether they are literals or not. Clearly there is room for other opinions (since @SimonSapin read it differently).
Personally, I am on the fence here. I somewhat agree with @SimonSapin that the number of regressions here feels too high. Part of the reason that I agree to go with a warning was to highlight this question so that we can have a wider discussion with more of the people who are affected.
For clarity, floating point literals at present match the same way as ==. Literals cannot be NaN. Therefore, I believe the only case where == can differ from "structural equality" with a floating point value has to do with 0 vs -0, which compare as equal but are clearly structurally unequal. (Does anyone have another example? I don't claim to be an expert on floating point edge cases.)
I take the following as a given (I'm curious if others disagree):
We should not change the runtime behavior of matching a floating point literal (e.g., to make 0 and -0 unequal) -- silent runtime changes seem to me to be almost never desirable if they can be avoided.
If we support floating point non-literal constants (NLC), they should behave the same as floating point literals.
This seems to imply that if we don't make things a hard error, we can't have floating point NLC that use a purely structural match. They would always match with ==. I don't see any fundamental problem here: plausibly we could say that all user-defined types use structural equality and built-in types have their own customized behaviors. We could even tweak the behavior for NaN if we wanted, though I think that having matching behave almost like == but different (i.e., 0 == -0 but NaN == NaN) feels even more confusing to me and I'm probably opposed.
This may or may not affect plans around constant generics. It's not obvious to me that dynamic match evaluation and equality for constant generics have to be particularly related, but I can see the appeal of trying to have one notion of "structural equality" that applies equally. Maybe someone wants to make the case (@eddyb? @withoutboats?) that the two are entangled? (I'd like to hear it again.)
In other words, I see a few options:
Make literals illegal.
Continue to allow literals, but not NLC.
but @withoutboats objects, and quite reasonably so, to the idea that we should draw this distinction. I agree it is surprising to me that a literal and a const would behave so differently.
Allow both literals and floating point constants to continue with current semantics
We used to check for NaN and error out; we could keep doing so for now, though if we ever support generics constants of floating point type that will no longer be viable -- or at least you couldn't use those constants in a match expression.
Personally, I don't see the point, though I wouldn't object to warning if we ever see a NaN constant in a match arm, since it is dead-code (and I would warn about it just as we try to always warn about dead code).
I am not sure whether an RFC ought to be required, whichever path we chose, but since there seems to be disagreement, it seems plausible to open an RFC amendment to finalize the decision.
Activity
SimonSapin commentedon May 10, 2017
RFC 1445 is about
constconstants. Why are float literals restricted as well?SimonSapin commentedon May 10, 2017
This is a breaking change (rejecting previously-accepted programs) but as far as I can tell this one is not part of an accepted RFC.
SimonSapin commentedon May 10, 2017
Is this a duplicate of #36890?
est31 commentedon May 10, 2017
Hmm a quick glance over the RFC seemed to confirm this.
Let's discuss this in #36890, okay?No, its separate. There are two separate lints. This one is about literals, the one tracked in that issue is about constants. I have opened the PR #41293 after finding out about #41255.
withoutboats commentedon May 10, 2017
From my perspective, primitive literals (as opposed to destructuring struct literals) are a kind of constant. The same questions raised by consts in that RFC are raised by primitive literals.
SimonSapin commentedon May 10, 2017
Yet the example given in #36890 uses literals.
Given that we have a language keyword named
const, I think it is reasonable to assume that constants arecontitems and nothing else. If a different definition of the term is intended, it should absolutely be defined explicitly. This is not the case in this RFC.est31 commentedon May 10, 2017
The example quoted in the tracking issue you linked never was implemented that way. I have asked about whether to create a separate lint or add the check to the existing one, and it was decided to create a separate lint.
I guess the example should be removed from that issue's description.
nikomatsakis commentedon May 10, 2017
I would definitely say that the RFC was intended to apply equally to all constants, whether they are literals or not. Clearly there is room for other opinions (since @SimonSapin read it differently).
Personally, I am on the fence here. I somewhat agree with @SimonSapin that the number of regressions here feels too high. Part of the reason that I agree to go with a warning was to highlight this question so that we can have a wider discussion with more of the people who are affected.
For clarity, floating point literals at present match the same way as
==. Literals cannot beNaN. Therefore, I believe the only case where==can differ from "structural equality" with a floating point value has to do with0vs-0, which compare as equal but are clearly structurally unequal. (Does anyone have another example? I don't claim to be an expert on floating point edge cases.)I take the following as a given (I'm curious if others disagree):
0and-0unequal) -- silent runtime changes seem to me to be almost never desirable if they can be avoided.This seems to imply that if we don't make things a hard error, we can't have floating point NLC that use a purely structural match. They would always match with
==. I don't see any fundamental problem here: plausibly we could say that all user-defined types use structural equality and built-in types have their own customized behaviors. We could even tweak the behavior forNaNif we wanted, though I think that having matching behave almost like==but different (i.e.,0 == -0butNaN == NaN) feels even more confusing to me and I'm probably opposed.This may or may not affect plans around constant generics. It's not obvious to me that dynamic
matchevaluation and equality for constant generics have to be particularly related, but I can see the appeal of trying to have one notion of "structural equality" that applies equally. Maybe someone wants to make the case (@eddyb? @withoutboats?) that the two are entangled? (I'd like to hear it again.)In other words, I see a few options:
constwould behave so differently.NaNand error out; we could keep doing so for now, though if we ever support generics constants of floating point type that will no longer be viable -- or at least you couldn't use those constants in amatchexpression.NaNconstant in a match arm, since it is dead-code (and I would warn about it just as we try to always warn about dead code).I am not sure whether an RFC ought to be required, whichever path we chose, but since there seems to be disagreement, it seems plausible to open an RFC amendment to finalize the decision.
60 remaining items
rdrpenguin04 commentedon Nov 3, 2023
What was the outcome?
RalfJung commentedon Nov 3, 2023
Unfortunately we didn't even get to floats, we were mainly discussing consts in patterns in general. Here is something of a summary.
NicoElbers commentedon Jan 23, 2024
Has there been any discussion since?
RalfJung commentedon Jan 23, 2024
Yes: rust-lang/rfcs#3535
Rollup merge of rust-lang#116284 - RalfJung:no-nan-match, r=cjgillot
Rollup merge of rust-lang#116284 - RalfJung:no-nan-match, r=cjgillot
Rollup merge of rust-lang#116284 - RalfJung:no-nan-match, r=cjgillot
Rollup merge of rust-lang#116284 - RalfJung:no-nan-match, r=cjgillot
Rollup merge of rust-lang#116284 - RalfJung:no-nan-match, r=cjgillot
Unrolled build for rust-lang#116284
Rollup merge of #116284 - RalfJung:no-nan-match, r=cjgillot
Changes to version 1.29.1 (b801ae664 2018-09-20)