Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add destructuring to catch clause #7990

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 36 additions & 6 deletions src/typing/statement.ml
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,15 @@ and statement cx : 'a -> (ALoc.t, ALoc.t * Type.t) Ast.Statement.t = Ast.Stateme
| Some p -> (match p with
| loc, Identifier {
Identifier.name = name_loc, ({ Ast.Identifier.name; comments= _ } as id);
annot = Ast.Type.Missing mloc;
annot;
optional;
} ->
let mloc = match annot with
| Ast.Type.Missing mloc -> mloc
| Ast.Type.Available (mloc, (loc, _)) ->
Flow.add_output cx Error_message.(EUnsupportedSyntax (loc, CatchParameterAnnotation));
mloc
in
let r = mk_reason (RCustom "catch") loc in
let t = Tvar.mk cx r in

Expand All @@ -695,11 +701,35 @@ and statement cx : 'a -> (ALoc.t, ALoc.t * Type.t) Ast.Statement.t = Ast.Stateme
},
abnormal_opt


| loc, Identifier _ ->
Flow.add_output cx
Error_message.(EUnsupportedSyntax (loc, CatchParameterAnnotation));
Tast_utils.error_mapper#catch_clause catch_clause, None
| ((ploc, Object _) as id)
| ((ploc, Array _) as id) ->
let id_reason = mk_reason RDestructuring ploc in
let annot = Destructuring.type_of_pattern id in
let annot = match annot with
| Ast.Type.Available (mloc, (loc, _)) ->
Flow.add_output cx Error_message.(EUnsupportedSyntax (loc, CatchParameterAnnotation));
Ast.Type.Missing mloc
| _ -> annot
in
let annot_t, _ = Anno.mk_type_annotation cx SMap.empty id_reason annot in
let init = Destructuring.empty annot_t ~annot:false in
let (stmts, abnormal_opt), id_ast = Env.in_lex_scope cx (fun () ->
let id_ast = Destructuring.pattern cx ~expr:expression init id ~f:(fun ~use_op loc name default t ->
let reason = mk_reason (RIdentifier name) loc in
Scope.(Env.bind_implicit_let ~state:State.Initialized Entry.CatchParamBinding cx name t loc);
Flow.flow cx (t, AssertImportIsValueT (reason, name));
Option.iter default ~f:(fun d ->
let default_t = Flow.mk_default cx reason d in
Flow.flow cx (default_t, UseT (use_op, t))
)
) in
check cx b, id_ast
) in
{ Try.CatchClause.
param = Some id_ast;
body = b_loc, { Block.body = stmts };
},
abnormal_opt

| loc, _ ->
Flow.add_output cx
Expand Down
44 changes: 44 additions & 0 deletions tests/try/destructuring-catch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/***
* @flow
*/

// object destructuring
function f() {
try {

} catch ({message}) {
message // ok
const foo: string = 1; // it typechecks
}
}

// array destructuring
function f() {
try {

} catch ([bar, baz]) {
bar // ok
baz // ok
const foo: string = 1; // it typechecks
}
}

// type annotation is banned
function f() {
try {

} catch ({message}: any) {
message // ok
const foo: string = 1; // it typechecks
}
}

// type annotation doesn't affect type
function f() {
try {

} catch ({message}: {message: string}) { // error
;(message: number) // ok
const foo: string = 1; // it typechecks
}
}
9 changes: 9 additions & 0 deletions tests/try/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,12 @@ function maz() {
}
var c: string = x[0]; // reachable
}

// type annotation is banned
function maz() {
try {
} catch (e: string) { // error
(e: number); // ok
var c: string = 1; // it typechecks
}
}
96 changes: 95 additions & 1 deletion tests/try/try.exp
Original file line number Diff line number Diff line change
@@ -1,3 +1,75 @@
Error ------------------------------------------------------------------------------------- destructuring-catch.js:11:25

Cannot assign `1` to `foo` because number [1] is incompatible with string [2].

destructuring-catch.js:11:25
11| const foo: string = 1; // it typechecks
^ [1]

References:
destructuring-catch.js:11:16
11| const foo: string = 1; // it typechecks
^^^^^^ [2]


Error ------------------------------------------------------------------------------------- destructuring-catch.js:22:25

Cannot assign `1` to `foo` because number [1] is incompatible with string [2].

destructuring-catch.js:22:25
22| const foo: string = 1; // it typechecks
^ [1]

References:
destructuring-catch.js:22:16
22| const foo: string = 1; // it typechecks
^^^^^^ [2]


Error ------------------------------------------------------------------------------------- destructuring-catch.js:30:23

Type annotations for catch parameters are not yet supported.

30| } catch ({message}: any) {
^^^


Error ------------------------------------------------------------------------------------- destructuring-catch.js:32:25

Cannot assign `1` to `foo` because number [1] is incompatible with string [2].

destructuring-catch.js:32:25
32| const foo: string = 1; // it typechecks
^ [1]

References:
destructuring-catch.js:32:16
32| const foo: string = 1; // it typechecks
^^^^^^ [2]


Error ------------------------------------------------------------------------------------- destructuring-catch.js:40:23

Type annotations for catch parameters are not yet supported.

40| } catch ({message}: {message: string}) { // error
^^^^^^^^^^^^^^^^^


Error ------------------------------------------------------------------------------------- destructuring-catch.js:42:25

Cannot assign `1` to `foo` because number [1] is incompatible with string [2].

destructuring-catch.js:42:25
42| const foo: string = 1; // it typechecks
^ [1]

References:
destructuring-catch.js:42:16
42| const foo: string = 1; // it typechecks
^^^^^^ [2]


Error ---------------------------------------------------------------------------------------------------- init.js:34:20

Cannot assign `x` to `y` because possibly uninitialized variable [1] is incompatible with number [2].
Expand Down Expand Up @@ -337,5 +409,27 @@ References:
^^^^^^ [2]


Error ---------------------------------------------------------------------------------------------------- test.js:78:15

Type annotations for catch parameters are not yet supported.

78| } catch (e: string) { // error
^^^^^^


Error ---------------------------------------------------------------------------------------------------- test.js:80:21

Cannot assign `1` to `c` because number [1] is incompatible with string [2].

test.js:80:21
80| var c: string = 1; // it typechecks
^ [1]

References:
test.js:80:12
80| var c: string = 1; // it typechecks
^^^^^^ [2]



Found 22 errors
Found 30 errors