Skip to content

Issue an error when numeric literals can incur precision loss #29863

Description

In JavaScript, you can write out a really really big (non-bigint) integer literal and get a completely different value.

0x6A09E667F3BCC908n == 0x6A09E667F3BCC908n // true

0x6A09E667F3BCC908n == 0x6A09E667F3BCC908  // false!?

It's worth asking whether or not a really really big integer values which have different observed and specified values are erroneous, and whether we can give users an error.

This would be a breaking change, but it's not clear who benefits from the current behavior.

See tc39/proposal-bigint#170 for where this came up (CC Daniel Ehrenberg (@littledan))

Activity

  1. changed the title [-]Error when numeric literals can incur floating point precision loss[/-] [+]Issue an error when numeric literals can incur floating point precision loss[/+] on Feb 11, 2019
  2. changed the title [-]Issue an error when numeric literals can incur floating point precision loss[/-] [+]Issue an error when numeric literals can incur precision loss[/+] on Feb 11, 2019
  3. littledan commented on Feb 12, 2019

    @littledan

    This is a great idea! However, this behavior been part of JS forever, so it might be good to start with a warning and see how it goes.

  4. DanielRosenwasser commented on Feb 12, 2019

    @DanielRosenwasser
    MemberAuthor

    We don't have warnings - just errors 😄🔥🌎🔥😄

  5. Kingwl commented on May 16, 2019

    @Kingwl
    Contributor

    Which behavior will be accepted?

    1. numerical compare to bigint literal
    2. numerical literal compare to bitint literal
    3. numerical literal compare to bigint
    4. numerical literal compare to bigint literal
  6. DanielRosenwasser commented on May 16, 2019

    @DanielRosenwasser
    MemberAuthor

    It's actually not about the comparisons themselves - it's about writing out an integer numeric literal whose value is too large to be represented accurately. In this specific case, I think we'd expect to error on a number like 0x6A09E667F3BCC908 with

    This numeric literal's value is too large to be represented accurately as an integer.
    

    I don't necessarily think we'd want the error for any numeric literal with a fractional component (e.g. no error on 9000000000000000000000000000.000000009).

  7. JoshuaKGoldberg commented on Sep 3, 2019

    @JoshuaKGoldberg
    Contributor

    This numeric literal's value is too large to be represented accurately as an integer.

    This is nice, but most don't know that 253 is the maximum for these. Perhaps a friendly error message would be something like:

    Numeric literal values equal to 2^53 or greater are too large to be represented accurately as an integer.

  8. JoshuaKGoldberg commented on Sep 3, 2019

    @JoshuaKGoldberg
    Contributor

    This is a great idea! However, this behavior been part of JS forever, so it might be good to start with a warning and see how it goes.

    How about a quick fix to add an n to the end of the numeric literal, if possible?

  9. DanielRosenwasser commented on Sep 3, 2019

    @DanielRosenwasser
    MemberAuthor

    Feel free to add a quick fix to insert the bigint suffix.

  10. added
    DeclinedThe issue was declined as something which matches the TypeScript vision
    and removed
    Breaking ChangeWould introduce errors in existing code
    Effort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".
    on Sep 3, 2019
  11. DanielRosenwasser commented on Sep 3, 2019

    @DanielRosenwasser
    MemberAuthor

    Feels like this is better off as some sort of lint rule. 😢

    Thanks for the PR though Josh Ghoulberg 👻 (@JoshuaKGoldberg).

  12. fatcerberus commented on Sep 7, 2019

    @fatcerberus

    IMO if I write out a numeric literal in the source text and assign it to a variable, without manipulating it in any way, and then observe a different value at runtime, I would wonder why the compiler didn’t yell at me (after spending probably several minutes debugging it :P)

    Only literals which can be exactly represented should be accepted.

    (Note that a codefix to change large numbers to bigint isn’t necessarily safe - mixing them with regular numbers in operations will produce runtime errors.)

  13. fatcerberus commented on Sep 7, 2019

    @fatcerberus

    Then again, 1.1 can’t be exactly represented in IEEE double either so it then becomes a question of how much precision loss you want to accept. Hmm.

    Also huge numbers like 1e100 would likely be errors too since it’s unlikely they won’t be rounded... nevermind, I take it back, this is a terrible idea. 😛

    I agree with Daniel Rosenwasser (@DanielRosenwasser), this is a job for a lint tool, not the compiler.

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

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions