Skip to content

Tracking issue for illegal_floating_point_literal_pattern compatibility lint #41620

Closed

Description

@est31

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:

fn main() {
    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"),
    }
}

Activity

  1. SimonSapin commented on May 10, 2017

    @SimonSapin
    Contributor

    RFC 1445 is about const constants. Why are float literals restricted as well?

  2. SimonSapin commented on May 10, 2017

    @SimonSapin
    Contributor

    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.

  3. SimonSapin commented on May 10, 2017

    @SimonSapin
    Contributor

    Is this a duplicate of #36890?

  4. est31 commented on May 10, 2017

    @est31
    MemberAuthor

    RFC 1445 is about const constants. Why are float literals restricted as well?

    Hmm a quick glance over the RFC seemed to confirm this. Let's discuss this in #36890, okay?

    Is this a duplicate of #36890?

    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.

  5. withoutboats commented on May 10, 2017

    @withoutboats
    Contributor

    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.

  6. SimonSapin commented on May 10, 2017

    @SimonSapin
    Contributor

    No, its separate. There are two separate lints. This one is about literals, the one tracked in that issue is about constants.

    Yet the example given in #36890 uses 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.

  7. est31 commented on May 10, 2017

    @est31
    MemberAuthor

    No, its separate. There are two separate lints. This one is about literals, the one tracked in that issue is about constants.

    Yet the example given in #36890 uses literals.

    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.

  8. nikomatsakis commented on May 10, 2017

    @nikomatsakis
    Contributor

    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.

  9. 60 remaining items

  10. rdrpenguin04 commented on Nov 3, 2023

    @rdrpenguin04

    What was the outcome?

  11. RalfJung commented on Nov 3, 2023

    @RalfJung
    Member

    Unfortunately we didn't even get to floats, we were mainly discussing consts in patterns in general. Here is something of a summary.

  12. NicoElbers commented on Jan 23, 2024

    @NicoElbers

    Has there been any discussion since?

  13. RalfJung commented on Jan 23, 2024

    @RalfJung
    Member
  14. added 5 commits that reference this issue on Feb 3, 2024
  15. added a commit that references this issue on Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-floating-pointArea: Floating point numbers and arithmeticA-patternsRelating to patterns and pattern matchingB-unstableBlocker: Implemented in the nightly compiler and unstable.C-future-incompatibilityCategory: Future-incompatibility lintsT-langRelevant to the language team

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions