From 83ff18e14e552f0bc11ba61bf4182348717ffa62 Mon Sep 17 00:00:00 2001 From: George Zahariev Date: Fri, 20 Dec 2024 13:45:29 -0800 Subject: [PATCH] [flow][match] Error on `as` patterns directly on binding patterns Summary: Error on `as` patterns directly on binding patterns. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D67502324 fbshipit-source-id: 82cb5634c4ac3bbf88cc8020dfe013982cc19458 --- src/typing/debug_js.ml | 1 + src/typing/errors/error_message.ml | 8 +++++++- src/typing/errors/flow_intermediate_error.ml | 2 ++ .../errors/flow_intermediate_error_types.ml | 1 + src/typing/match_pattern.ml | 3 +++ tests/match/match.exp | 18 +++++++++++++++++- tests/match/pattern-errors.js | 10 ++++++++++ 7 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/typing/debug_js.ml b/src/typing/debug_js.ml index c389248c1b7..bf0430efefc 100644 --- a/src/typing/debug_js.ml +++ b/src/typing/debug_js.ml @@ -1913,6 +1913,7 @@ let dump_error_message = | EMatchDuplicateObjectProperty { loc; name } -> spf "EMatchDuplicateObjectProperty (%s) (%s)" (string_of_aloc loc) name | EMatchBindingInOrPattern { loc } -> spf "EMatchBindingInOrPattern (%s)" (string_of_aloc loc) + | EMatchInvalidAsPattern { loc } -> spf "EMatchInvalidAsPattern (%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 f1d2277a401..37b25b6c5dc 100644 --- a/src/typing/errors/error_message.ml +++ b/src/typing/errors/error_message.ml @@ -630,6 +630,7 @@ and 'loc t' = name: string; } | EMatchBindingInOrPattern of { loc: 'loc } + | EMatchInvalidAsPattern of { loc: 'loc } (* Dev only *) | EDevOnlyRefinedLocInfo of { refined_loc: 'loc; @@ -1440,6 +1441,7 @@ let rec map_loc_of_error_message (f : 'a -> 'b) : 'a t' -> 'b t' = | EMatchDuplicateObjectProperty { loc; name } -> EMatchDuplicateObjectProperty { loc = f loc; name } | EMatchBindingInOrPattern { loc } -> EMatchBindingInOrPattern { loc = f loc } + | EMatchInvalidAsPattern { loc } -> EMatchInvalidAsPattern { loc = f loc } | EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info } -> EDevOnlyInvalidatedRefinementInfo { @@ -1743,7 +1745,8 @@ let util_use_op_of_msg nope util = function | EMatchInvalidUnaryZero _ | EMatchInvalidUnaryPlusBigInt _ | EMatchDuplicateObjectProperty _ - | EMatchBindingInOrPattern _ -> + | EMatchBindingInOrPattern _ + | EMatchInvalidAsPattern _ -> nope (* Not all messages (i.e. those whose locations are based on use_ops) have locations that can be @@ -1951,6 +1954,7 @@ let loc_of_msg : 'loc t' -> 'loc option = function | EMatchInvalidUnaryPlusBigInt { loc } -> Some loc | EMatchDuplicateObjectProperty { loc; _ } -> Some loc | EMatchBindingInOrPattern { loc } -> Some loc + | EMatchInvalidAsPattern { loc } -> Some loc | EDevOnlyRefinedLocInfo { refined_loc; refining_locs = _ } -> Some refined_loc | EDevOnlyInvalidatedRefinementInfo { read_loc; invalidation_info = _ } -> Some read_loc | EUnableToSpread _ @@ -2907,6 +2911,7 @@ let friendly_message_of_msg = function | EMatchDuplicateObjectProperty { loc = _; name } -> Normal (MessageMatchDuplicateObjectProperty { name }) | EMatchBindingInOrPattern { loc = _ } -> Normal MessageMatchBindingInOrPattern + | EMatchInvalidAsPattern { loc = _ } -> Normal MessageMatchInvalidAsPattern let defered_in_speculation = function | EUntypedTypeImport _ @@ -3250,3 +3255,4 @@ let error_code_of_message err : error_code option = | EMatchInvalidUnaryPlusBigInt _ -> Some MatchInvalidPattern | EMatchDuplicateObjectProperty _ -> Some MatchInvalidPattern | EMatchBindingInOrPattern _ -> Some MatchInvalidPattern + | EMatchInvalidAsPattern _ -> Some MatchInvalidPattern diff --git a/src/typing/errors/flow_intermediate_error.ml b/src/typing/errors/flow_intermediate_error.ml index 0c6266b4538..2f23f4ed957 100644 --- a/src/typing/errors/flow_intermediate_error.ml +++ b/src/typing/errors/flow_intermediate_error.ml @@ -4010,6 +4010,8 @@ let to_printable_error : [text "Duplicate property "; code name; text " in object pattern."] | MessageMatchBindingInOrPattern -> [text "New bindings in 'or' patterns are not yet supported."] + | MessageMatchInvalidAsPattern -> + [text "Invalid "; code "as"; text " pattern. Direct use on a binding pattern is not allowed."] 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 36c27d52577..f486b6b4c51 100644 --- a/src/typing/errors/flow_intermediate_error_types.ml +++ b/src/typing/errors/flow_intermediate_error_types.ml @@ -904,6 +904,7 @@ type 'loc message = | MessageMatchInvalidUnaryPlusBigInt | MessageMatchDuplicateObjectProperty of { name: string } | MessageMatchBindingInOrPattern + | MessageMatchInvalidAsPattern 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 cd61f1bb076..264579c20f1 100644 --- a/src/typing/match_pattern.ml +++ b/src/typing/match_pattern.ml @@ -165,6 +165,9 @@ let rec pattern_ cx ~on_identifier ~on_expression ~on_binding ~in_or_pattern acc in OrPattern { OrPattern.patterns; comments } | AsPattern { AsPattern.pattern = p; target; comments } -> + (match p with + | (_, BindingPattern _) -> Flow_js.add_output cx (Error_message.EMatchInvalidAsPattern { loc }) + | _ -> ()); let p = pattern_ cx ~on_identifier ~on_expression ~on_binding ~in_or_pattern acc p in let target = match target with diff --git a/tests/match/match.exp b/tests/match/match.exp index 418e2c7fcf5..7006ec53fb7 100644 --- a/tests/match/match.exp +++ b/tests/match/match.exp @@ -652,6 +652,22 @@ New bindings in 'or' patterns are not yet supported. [match-invalid-pattern] ^ +Error ------------------------------------------------------------------------------------------ pattern-errors.js:109:5 + +Invalid `as` pattern. Direct use on a binding pattern is not allowed. [match-invalid-pattern] + + 109| const a as b: 0, // ERROR + ^^^^^^^^^^^^ + + +Error ------------------------------------------------------------------------------------------ pattern-errors.js:110:5 + +Invalid `as` pattern. Direct use on a binding pattern is not allowed. [match-invalid-pattern] + + 110| const a as const b: 0, // ERROR + ^^^^^^^^^^^^^^^^^^ + + Error -------------------------------------------------------------------------------------------------- patterns.js:9:3 Cannot cast `out` to empty because number [1] is incompatible with empty [2]. [incompatible-cast] @@ -777,4 +793,4 @@ References: -Found 62 errors +Found 64 errors diff --git a/tests/match/pattern-errors.js b/tests/match/pattern-errors.js index 2753a017f8b..5b3f01df45f 100644 --- a/tests/match/pattern-errors.js +++ b/tests/match/pattern-errors.js @@ -100,3 +100,13 @@ _ | {...const a}: 0, // ERROR }; } + +// As pattern on binding pattern +{ + declare const x: [boolean]; + + const e1 = match (x) { + const a as b: 0, // ERROR + const a as const b: 0, // ERROR + } +}