Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upMatching on floating-point literal values is totally allowed and shouldn't be #41255
Comments
carols10cents
referenced this issue
Apr 12, 2017
Closed
Tracking issue for `illegal_floating_point_constant_pattern` compatibility lint #36890
This comment has been minimized.
This comment has been minimized.
|
There seem to be three options:
idk maybe a crater run should be done to find out what is best. |
This comment has been minimized.
This comment has been minimized.
|
@est31 indeed, a crater run seems warranted. |
nikomatsakis
added
I-nominated
T-compiler
labels
Apr 13, 2017
This comment has been minimized.
This comment has been minimized.
|
Nominating for compiler team discussion on best way to proceed and prioritization. Seems to me we ought to settle this pretty quickly one way or another. |
This comment has been minimized.
This comment has been minimized.
|
triage: P-high This is time-sensitive, so we gotta act if we are ever going to. Assigning to @pnkfelix. |
rust-highfive
added
P-high
and removed
I-nominated
labels
Apr 13, 2017
nikomatsakis
assigned
pnkfelix
Apr 13, 2017
This comment has been minimized.
This comment has been minimized.
|
I've filed two PRs #41292 for removing the use of a floating point match from the compiler and #41293 for a crater run to test the most strict solution -- to add it to the existing lint without changing the deny-by-default status. Independent from whether that strategy will be chosen in the end, it gives us an initial number of crates that would be affected by the change. #41293 includes #41292 already to make a crater run possible without #41292 being merged. |
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Apr 14, 2017
This comment has been minimized.
This comment has been minimized.
|
This is arguable. Floats are built-in types known to the compiler, you don't have to run any user-defined code to match on them. Another analogy is that float literals are the same thing as variants for non- match xxx {
NON_STRUCTURAL_MATCH_CONST => {} // Not OK, constant
NonStructuralMatch { field } => {} // OK, variant
FLOAT_CONST => {} // Not OK, constant
1.0 => {} // OK, variant
} |
This comment has been minimized.
This comment has been minimized.
|
The number of regressions in #41293 is also relatively large. |
This comment has been minimized.
This comment has been minimized.
|
As I wrote on the comment, I too am second-guessing this rule. I think at this point I'm inclined to say that matching on floats uses |
This comment has been minimized.
This comment has been minimized.
While this is true, most (all?) of the time there is some visual hint that the compiler may insert extra logic. E.g. if I see a |
This comment has been minimized.
This comment has been minimized.
|
@aidanhs we'd also have to settle what NaN ought to do (would it ever be a match?). My inclination would be to make floating point matches align with what |
nikomatsakis
added
the
T-lang
label
Apr 20, 2017
This comment has been minimized.
This comment has been minimized.
|
If we had to choose, personally I'd prefer NaN to be matched! My current intuition is that a pattern match is quite distinct from Of course, there are some annoyances since
But...is there actually any need to make a decision for NaN? There's no NaN literal, so there's no way to write it in a pattern in a way that rustc accepts (I think? It's not even rejected under the lint, it's rejected as an irrefutable pattern). And if you can't write it on the left, it doesn't matter if it's ever on the right. Continuing a compile-time error that already exists is definitely my favourite approach for NaN. |
This comment has been minimized.
This comment has been minimized.
If you allow the lint, this compiles: https://is.gd/U8BM1Y |
This comment has been minimized.
This comment has been minimized.
I'd prefer to accept both named constants and constant patterns in a consistent way, myself. I also agree that NaN should match NaN (in general, I think that if you can do both UPDATE: (But I know that nullary enum variants do not necessarily behave this way -- I rationalize this by the idea that matching a variant is distinct from matching a constant, but elsewhere we don't draw that distinction.) |
This comment has been minimized.
This comment has been minimized.
|
So @aidanhs tactfully pointed out to me on IRC that I wrote two contradictory things:
and
To be honest, I'm not sure which of these values I hold most dearly anymore! I do have the notion that pattern matching (for enums, as you say) is doing "variant testing", which is a distinct operation from And the bigger question here is when (if ever) we would allow matching constants of generic type (which will start to arise when we get to functions that can be generic over constants). I'd like to allow for that future, which seems to imply that one of three things is true:
So, unless I'm missing something, we basically have to choose between:
|
This comment has been minimized.
This comment has been minimized.
|
@eddyb @withoutboats -- I'd appreciate your thoughts on this comment, and in particular about the implications for unification. For context, we're talking about the meaning of floating point constants in match, but I'm bringing in more general questions of what it means to have a constant as a pattern anyhow. In any case, I suppose "no constants of generic type in match" is not the end of the world. After all, one can write the relevant code using pattern guards. |
This comment has been minimized.
This comment has been minimized.
|
We could make that trait about pattern-matching instead of "equality" (i.e. if we ever add custom patterns, it could be through that trait), and while it might be customizable, it couldn't escape our restrictions on pattern-matching. E.g. maybe terrible, but: trait Inject<T...; const IN: T> {
const VALUE: Self;
}
struct Point { x: i32, y: i32 }
impl<const x: i32, const y: i32> Inject<i32, i32; {(x, y)}> for Point {
const VALUE = Point { x, y };
}This looks worse than refinement typing, but it probably has some usecases. |
This comment has been minimized.
This comment has been minimized.
I suppose that is another way of looking at it -- that is, instead of "another kind of equality", what we have instead is a trait that defines what pattern matching a value means. This could be more than marker trait -- that is, it could open the door to overloaded pattern matching, which would be potentially quite cool. (This all works better, of course, if pattern variants have their own types.) I could get behind that story, though we'd have to have some sort of "fallback" behavior -- or default impl -- since we currently permit pattern matching for things that derive |
This comment has been minimized.
This comment has been minimized.
|
I expect the automatic implementation to hook into |
This comment has been minimized.
This comment has been minimized.
|
I think I'd prefer to just disallow float literals in patterns. |
nikomatsakis
added
I-nominated
and removed
T-compiler
labels
Apr 27, 2017
This comment has been minimized.
This comment has been minimized.
|
Nominating for lang team discussion today. |
This comment has been minimized.
This comment has been minimized.
|
We discussed this in the @rust-lang/lang team meeting. There was some disagreement about the best path forward, but we agreed that as a compromise we could start issuing warnings (not deny by default) for floating point literals, and see where that takes us. That was the RFC that we merged, after all. |
nikomatsakis
removed
the
I-nominated
label
Apr 28, 2017
This comment has been minimized.
This comment has been minimized.
|
Sorry, I didn't give many details from our discussion (which actually took quite some time). I don't think we really covered any new ground that's not already in this discussion thread, though. |
brson
added
the
I-wrong
label
May 4, 2017
bors
added a commit
that referenced
this issue
May 8, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
May 9, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
May 9, 2017
This comment has been minimized.
This comment has been minimized.
|
Was a crater run made, in the end? This breaks Servo, which unfortunately is not part of Crater. |
This comment has been minimized.
This comment has been minimized.
Do you mean "this would break servo if it became a hard error"? (But we should take it to #41620 in any case.) |
This comment has been minimized.
This comment has been minimized.
Yes, I think this particular crate has |
lnicola
referenced this issue
Jul 16, 2017
Open
Tracking issue for RFC #495 (features `slice_patterns` and `advanced_slice_patterns`) #23121
aturon
added
T-compiler
and removed
T-lang
labels
Jul 20, 2017
This comment has been minimized.
This comment has been minimized.
|
Refiling as T-compiler; what's left here is to move to a hard error. The warning went out in 1.18. |
Mark-Simulacrum
added
the
C-bug
label
Jul 27, 2017
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium |
rust-highfive
added
P-medium
and removed
P-high
labels
Jul 27, 2017
Mark-Simulacrum
removed
the
I-wrong
label
Jul 28, 2017
This comment has been minimized.
This comment has been minimized.
|
Heads up: #46882 removes the hard error for matching on float constants and produces the same future compat warning. |
This comment has been minimized.
This comment has been minimized.
|
I'm going to close this in favor of the tracking issue for the lint, since it seems like that's where discussion should move. |
carols10cents commentedApr 12, 2017
Per this comment on the tracking issue for disallowing the use of constants set to floating point numbers (which errors as expected today), @nikomatsakis says the intention was to disallow floating point literal values in matches, but uh... this is totally accepted by Rust 1.16.0:
This prints "thirteen point four". I expected to get a compiler error like the one I get if I change a floating point value in the match to a constant:
results in: