Skip to content

Commit

Permalink
[flow][match] Error on invalid unary pattern on 0
Browse files Browse the repository at this point in the history
Summary:
Error on invalid unary pattern on `0`.

The spec suggests using `Object.is` equality for this instead of `===`, which distinguishes `+0` and `-0`. Flow doesn't model this. Let's just avoid it for now.

Changelog: [internal]

Reviewed By: SamChou19815

Differential Revision: D67502321

fbshipit-source-id: ce6bf7936edc4d5d9cd95d6177690f075c0dbdf6
  • Loading branch information
gkz authored and facebook-github-bot committed Dec 20, 2024
1 parent ea7dadd commit 67befeb
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/typing/debug_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1907,6 +1907,7 @@ let dump_error_message =
(Flow_ast_utils.string_of_variable_kind kind)
| EMatchInvalidObjectPropertyLiteral { loc } ->
spf "EMatchInvalidObjectPropertyLiteral (%s)" (string_of_aloc loc)
| EMatchInvalidUnaryZero { loc } -> spf "EMatchInvalidUnaryZero (%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 = _ } ->
Expand Down
8 changes: 7 additions & 1 deletion src/typing/errors/error_message.ml
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ and 'loc t' =
kind: Flow_ast.Variable.kind;
}
| EMatchInvalidObjectPropertyLiteral of { loc: 'loc }
| EMatchInvalidUnaryZero of { loc: 'loc }
(* Dev only *)
| EDevOnlyRefinedLocInfo of {
refined_loc: 'loc;
Expand Down Expand Up @@ -1428,6 +1429,7 @@ let rec map_loc_of_error_message (f : 'a -> 'b) : 'a t' -> 'b t' =
EMatchNotExhaustive { loc = f loc; reason = map_reason reason }
| EMatchInvalidBindingKind { loc; kind } -> EMatchInvalidBindingKind { loc = f loc; kind }
| EMatchInvalidObjectPropertyLiteral { loc } -> EMatchInvalidObjectPropertyLiteral { loc = f loc }
| EMatchInvalidUnaryZero { loc } -> EMatchInvalidUnaryZero { loc = f loc }
| EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info } ->
EDevOnlyInvalidatedRefinementInfo
{
Expand Down Expand Up @@ -1727,7 +1729,8 @@ let util_use_op_of_msg nope util = function
| ECannotCallReactComponent _
| EMatchNotExhaustive _
| EMatchInvalidBindingKind _
| EMatchInvalidObjectPropertyLiteral _ ->
| EMatchInvalidObjectPropertyLiteral _
| EMatchInvalidUnaryZero _ ->
nope

(* Not all messages (i.e. those whose locations are based on use_ops) have locations that can be
Expand Down Expand Up @@ -1931,6 +1934,7 @@ let loc_of_msg : 'loc t' -> 'loc option = function
| EMatchNotExhaustive { loc; _ } -> Some loc
| EMatchInvalidBindingKind { loc; _ } -> Some loc
| EMatchInvalidObjectPropertyLiteral { loc } -> Some loc
| EMatchInvalidUnaryZero { loc } -> Some loc
| EDevOnlyRefinedLocInfo { refined_loc; refining_locs = _ } -> Some refined_loc
| EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info = _ } -> Some read_loc
| EUnableToSpread _
Expand Down Expand Up @@ -2882,6 +2886,7 @@ let friendly_message_of_msg = function
| EMatchInvalidBindingKind { loc = _; kind } -> Normal (MessageMatchInvalidBindingKind { kind })
| EMatchInvalidObjectPropertyLiteral { loc = _ } ->
Normal MessageMatchInvalidObjectPropertyLiteral
| EMatchInvalidUnaryZero { loc = _ } -> Normal MessageMatchInvalidUnaryZero

let defered_in_speculation = function
| EUntypedTypeImport _
Expand Down Expand Up @@ -3221,3 +3226,4 @@ let error_code_of_message err : error_code option =
| EMatchNotExhaustive _ -> Some MatchNotExhaustive
| EMatchInvalidBindingKind _ -> Some MatchInvalidPattern
| EMatchInvalidObjectPropertyLiteral _ -> Some MatchInvalidPattern
| EMatchInvalidUnaryZero _ -> Some MatchInvalidPattern
2 changes: 2 additions & 0 deletions src/typing/errors/flow_intermediate_error.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4002,6 +4002,8 @@ let to_printable_error :
text "Unsupported object property literal in match pattern. ";
text "String literals and int-like number literals are supported.";
]
| MessageMatchInvalidUnaryZero ->
[text "Unary pattern on "; code "0"; text " is not supported."]
in
let rec convert_error_message { kind; loc; error_code; root; message; misplaced_source_file = _ }
=
Expand Down
1 change: 1 addition & 0 deletions src/typing/errors/flow_intermediate_error_types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ type 'loc message =
| MessageMatchNotExhaustive of 'loc virtual_reason
| MessageMatchInvalidBindingKind of { kind: Flow_ast.Variable.kind }
| MessageMatchInvalidObjectPropertyLiteral
| MessageMatchInvalidUnaryZero

type 'loc intermediate_error = {
kind: Flow_errors_utils.error_kind;
Expand Down
8 changes: 7 additions & 1 deletion src/typing/match_pattern.ml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,13 @@ let rec pattern cx ~on_identifier ~on_expression ~on_binding acc (loc, p) :
| StringPattern x -> StringPattern x
| BooleanPattern x -> BooleanPattern x
| NullPattern x -> NullPattern x
| UnaryPattern x -> UnaryPattern x
| UnaryPattern x ->
let { UnaryPattern.argument; _ } = x in
(match argument with
| (_, UnaryPattern.NumberLiteral { Ast.NumberLiteral.value = 0.0; _ }) ->
Flow_js.add_output cx (Error_message.EMatchInvalidUnaryZero { loc })
| _ -> ());
UnaryPattern x
| MemberPattern mem ->
let (_, mem) = member cx ~on_identifier ~on_expression mem in
MemberPattern mem
Expand Down
27 changes: 26 additions & 1 deletion tests/match/match.exp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,31 @@ Cannot use `var` for match pattern binding. Only `const` is allowed. [match-inva
^^^^^


Error ------------------------------------------------------------------------------------------- pattern-errors.js:25:6

Unsupported object property literal in match pattern. String literals and int-like number literals are supported.
[match-invalid-pattern]

25| {1.1: _}: 0, // ERROR
^^^


Error ------------------------------------------------------------------------------------------- pattern-errors.js:35:5

Unary pattern on `0` is not supported. [match-invalid-pattern]

35| -0: true, // ERROR
^^


Error ------------------------------------------------------------------------------------------- pattern-errors.js:36:5

Unary pattern on `0` is not supported. [match-invalid-pattern]

36| +0: true, // ERROR
^^


Error -------------------------------------------------------------------------------------------------- patterns.js:9:3

Cannot cast `out` to empty because number [1] is incompatible with empty [2]. [incompatible-cast]
Expand Down Expand Up @@ -602,4 +627,4 @@ References:



Found 44 errors
Found 47 errors
21 changes: 21 additions & 0 deletions tests/match/pattern-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,24 @@
var a: 0, // ERROR
};
}

// Invalid numeric property
{
declare const x: {1: true};

const e1 = match (x) {
{1.1: _}: 0, // ERROR
_: 0,
};
}

// Unary pattern on `0` banned
{
declare const x: 0;

const e1 = match (x) {
-0: true, // ERROR
+0: true, // ERROR
0: true, // OK
};
}

0 comments on commit 67befeb

Please sign in to comment.