From 82c1fa3205e2c7f45f608a470b3c13af4d63c9bd Mon Sep 17 00:00:00 2001 From: George Zahariev Date: Fri, 20 Dec 2024 13:17:33 -0800 Subject: [PATCH] [flow][match] Error on unary pattern `+` on bigint literal Summary: Error on unary pattern `+` on bigint literal (e.g. `+1n`). This is not allowed in JS in general. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D67502323 fbshipit-source-id: 0471e0d1093e2026beebf7353fb9c01c5139cbe8 --- src/typing/debug_js.ml | 2 ++ src/typing/errors/error_message.ml | 8 +++++++- src/typing/errors/flow_intermediate_error.ml | 2 ++ src/typing/errors/flow_intermediate_error_types.ml | 1 + src/typing/match_pattern.ml | 8 +++++--- tests/match/match.exp | 10 +++++++++- tests/match/pattern-errors.js | 10 ++++++++++ 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/typing/debug_js.ml b/src/typing/debug_js.ml index 65bed91da11..fed29df77ae 100644 --- a/src/typing/debug_js.ml +++ b/src/typing/debug_js.ml @@ -1908,6 +1908,8 @@ let dump_error_message = | EMatchInvalidObjectPropertyLiteral { loc } -> spf "EMatchInvalidObjectPropertyLiteral (%s)" (string_of_aloc loc) | EMatchInvalidUnaryZero { loc } -> spf "EMatchInvalidUnaryZero (%s)" (string_of_aloc loc) + | EMatchInvalidUnaryPlusBigInt { loc } -> + spf "EMatchInvalidUnaryBigInt (%s)" (string_of_aloc loc) | EDevOnlyRefinedLocInfo { refined_loc; refining_locs = _ } -> spf "EDevOnlyRefinedLocInfo {refined_loc=%s}" (string_of_aloc refined_loc) | EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info = _ } -> diff --git a/src/typing/errors/error_message.ml b/src/typing/errors/error_message.ml index 21846bbcff8..f12c7e4de7e 100644 --- a/src/typing/errors/error_message.ml +++ b/src/typing/errors/error_message.ml @@ -624,6 +624,7 @@ and 'loc t' = } | EMatchInvalidObjectPropertyLiteral of { loc: 'loc } | EMatchInvalidUnaryZero of { loc: 'loc } + | EMatchInvalidUnaryPlusBigInt of { loc: 'loc } (* Dev only *) | EDevOnlyRefinedLocInfo of { refined_loc: 'loc; @@ -1430,6 +1431,7 @@ let rec map_loc_of_error_message (f : 'a -> 'b) : 'a t' -> 'b t' = | EMatchInvalidBindingKind { loc; kind } -> EMatchInvalidBindingKind { loc = f loc; kind } | EMatchInvalidObjectPropertyLiteral { loc } -> EMatchInvalidObjectPropertyLiteral { loc = f loc } | EMatchInvalidUnaryZero { loc } -> EMatchInvalidUnaryZero { loc = f loc } + | EMatchInvalidUnaryPlusBigInt { loc } -> EMatchInvalidUnaryPlusBigInt { loc = f loc } | EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info } -> EDevOnlyInvalidatedRefinementInfo { @@ -1730,7 +1732,8 @@ let util_use_op_of_msg nope util = function | EMatchNotExhaustive _ | EMatchInvalidBindingKind _ | EMatchInvalidObjectPropertyLiteral _ - | EMatchInvalidUnaryZero _ -> + | EMatchInvalidUnaryZero _ + | EMatchInvalidUnaryPlusBigInt _ -> nope (* Not all messages (i.e. those whose locations are based on use_ops) have locations that can be @@ -1935,6 +1938,7 @@ let loc_of_msg : 'loc t' -> 'loc option = function | EMatchInvalidBindingKind { loc; _ } -> Some loc | EMatchInvalidObjectPropertyLiteral { loc } -> Some loc | EMatchInvalidUnaryZero { loc } -> Some loc + | EMatchInvalidUnaryPlusBigInt { loc } -> Some loc | EDevOnlyRefinedLocInfo { refined_loc; refining_locs = _ } -> Some refined_loc | EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info = _ } -> Some read_loc | EUnableToSpread _ @@ -2887,6 +2891,7 @@ let friendly_message_of_msg = function | EMatchInvalidObjectPropertyLiteral { loc = _ } -> Normal MessageMatchInvalidObjectPropertyLiteral | EMatchInvalidUnaryZero { loc = _ } -> Normal MessageMatchInvalidUnaryZero + | EMatchInvalidUnaryPlusBigInt { loc = _ } -> Normal MessageMatchInvalidUnaryPlusBigInt let defered_in_speculation = function | EUntypedTypeImport _ @@ -3227,3 +3232,4 @@ let error_code_of_message err : error_code option = | EMatchInvalidBindingKind _ -> Some MatchInvalidPattern | EMatchInvalidObjectPropertyLiteral _ -> Some MatchInvalidPattern | EMatchInvalidUnaryZero _ -> Some MatchInvalidPattern + | EMatchInvalidUnaryPlusBigInt _ -> Some MatchInvalidPattern diff --git a/src/typing/errors/flow_intermediate_error.ml b/src/typing/errors/flow_intermediate_error.ml index 8f195bc3f48..0420628c1aa 100644 --- a/src/typing/errors/flow_intermediate_error.ml +++ b/src/typing/errors/flow_intermediate_error.ml @@ -4004,6 +4004,8 @@ let to_printable_error : ] | MessageMatchInvalidUnaryZero -> [text "Unary pattern on "; code "0"; text " is not supported."] + | MessageMatchInvalidUnaryPlusBigInt -> + [text "Unary pattern "; code "+"; text " on bigint literal is not supported."] in let rec convert_error_message { kind; loc; error_code; root; message; misplaced_source_file = _ } = diff --git a/src/typing/errors/flow_intermediate_error_types.ml b/src/typing/errors/flow_intermediate_error_types.ml index 8a40f3d1b97..84a945c1ae0 100644 --- a/src/typing/errors/flow_intermediate_error_types.ml +++ b/src/typing/errors/flow_intermediate_error_types.ml @@ -901,6 +901,7 @@ type 'loc message = | MessageMatchInvalidBindingKind of { kind: Flow_ast.Variable.kind } | MessageMatchInvalidObjectPropertyLiteral | MessageMatchInvalidUnaryZero + | MessageMatchInvalidUnaryPlusBigInt type 'loc intermediate_error = { kind: Flow_errors_utils.error_kind; diff --git a/src/typing/match_pattern.ml b/src/typing/match_pattern.ml index b191dd4fe82..b29152a7386 100644 --- a/src/typing/match_pattern.ml +++ b/src/typing/match_pattern.ml @@ -140,10 +140,12 @@ let rec pattern cx ~on_identifier ~on_expression ~on_binding acc (loc, p) : | BooleanPattern x -> BooleanPattern x | NullPattern x -> NullPattern x | UnaryPattern x -> - let { UnaryPattern.argument; _ } = x in - (match argument with - | (_, UnaryPattern.NumberLiteral { Ast.NumberLiteral.value = 0.0; _ }) -> + let { UnaryPattern.operator; argument; _ } = x in + (match (operator, argument) with + | (_, (_, UnaryPattern.NumberLiteral { Ast.NumberLiteral.value = 0.0; _ })) -> Flow_js.add_output cx (Error_message.EMatchInvalidUnaryZero { loc }) + | (UnaryPattern.Plus, (_, UnaryPattern.BigIntLiteral _)) -> + Flow_js.add_output cx (Error_message.EMatchInvalidUnaryPlusBigInt { loc }) | _ -> ()); UnaryPattern x | MemberPattern mem -> diff --git a/tests/match/match.exp b/tests/match/match.exp index 9a1cd651aae..ccd72a1cd31 100644 --- a/tests/match/match.exp +++ b/tests/match/match.exp @@ -502,6 +502,14 @@ Unary pattern on `0` is not supported. [match-invalid-pattern] ^^ +Error ------------------------------------------------------------------------------------------- pattern-errors.js:46:5 + +Unary pattern `+` on bigint literal is not supported. [match-invalid-pattern] + + 46| +1n: true, // ERROR + ^^^ + + Error -------------------------------------------------------------------------------------------------- patterns.js:9:3 Cannot cast `out` to empty because number [1] is incompatible with empty [2]. [incompatible-cast] @@ -627,4 +635,4 @@ References: -Found 47 errors +Found 48 errors diff --git a/tests/match/pattern-errors.js b/tests/match/pattern-errors.js index f318a0f3b2c..bce30343899 100644 --- a/tests/match/pattern-errors.js +++ b/tests/match/pattern-errors.js @@ -37,3 +37,13 @@ 0: true, // OK }; } + +// Unary `+` on bigint banned +{ + declare const x: 1n; + + const e1 = match (x) { + +1n: true, // ERROR + 1n: true, // OK + }; +}