Skip to content

Commit

Permalink
[flow][match] Fix issue with "as" pattern nested inside objects not r…
Browse files Browse the repository at this point in the history
…efining correct location

Summary:
Fix issue with "as" pattern nested inside objects not refining correct location.

Changelog: [internal]

Reviewed By: SamChou19815

Differential Revision: D68523162

fbshipit-source-id: 4faf2f3ac5bdae653eab478ec267773872ec3f80
  • Loading branch information
gkz authored and facebook-github-bot committed Jan 23, 2025
1 parent a4767a5 commit 85e5e65
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 71 deletions.
3 changes: 2 additions & 1 deletion src/analysis/env_builder/__tests__/name_def_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1712,7 +1712,8 @@ let%expect_test "match_pattern_as" =
[
(2, 1) to (2, 6) => val (2, 8) to (2, 9);
(3, 13) to (3, 14) => (val (3, 2) to (3, 19)).foo;
(3, 2) to (3, 15) => val (3, 2) to (3, 19)
(3, 2) to (3, 15) => val (3, 2) to (3, 19);
(3, 8) to (3, 9) => exp (3, 8) to (3, 9) (hint = [])
] |}]

let%expect_test "match_pattern_nested" =
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/env_builder/name_resolver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3135,7 +3135,7 @@ module Make (Context : C) (FlowAPIUtils : F with type cx = Context.t) :
acc
refi
(loc, Ast.Expression.BigIntLiteral { Ast.BigIntLiteral.raw; value; comments }))
| (_, AsPattern { AsPattern.pattern; _ }) -> recurse arg pattern
| (_, AsPattern { AsPattern.pattern; _ }) -> recurse acc pattern
| (loc, BindingPattern _)
| (loc, WildcardPattern _) ->
(match RefinementKey.of_expression acc with
Expand Down
138 changes: 69 additions & 69 deletions tests/match/match.exp
Original file line number Diff line number Diff line change
Expand Up @@ -198,202 +198,202 @@ References:
^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:131:14
Error ----------------------------------------------------------------------------------------------- matching.js:140:14

`match` is not exhaustively checked: number literal `2` [1] has not been fully checked against by the match patterns
below. [match-not-exhaustive]

matching.js:131:14
131| const e2 = match (f()) { // ERROR: `2` not checked
matching.js:140:14
140| const e2 = match (f()) { // ERROR: `2` not checked
^^^^^

References:
matching.js:123:30
123| declare const f: () => 1 | 2;
matching.js:132:30
132| declare const f: () => 1 | 2;
^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:145:14
Error ----------------------------------------------------------------------------------------------- matching.js:154:14

`match` is not exhaustively checked: number literal `3` [1] has not been fully checked against by the match patterns
below. [match-not-exhaustive]

matching.js:145:14
145| const e2 = match (x) { // ERROR: `3` not checked
matching.js:154:14
154| const e2 = match (x) { // ERROR: `3` not checked
^^^^^

References:
matching.js:138:28
138| declare const x: 1 | 2 | 3;
matching.js:147:28
147| declare const x: 1 | 2 | 3;
^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:156:14
Error ----------------------------------------------------------------------------------------------- matching.js:165:14

`match` is not exhaustively checked: number literal `2` [1] has not been fully checked against by the match patterns
below. [match-not-exhaustive]

matching.js:156:14
156| const e1 = match (x) { // ERROR: `2` not checked
matching.js:165:14
165| const e1 = match (x) { // ERROR: `2` not checked
^^^^^

References:
matching.js:152:24
152| declare const x: 1 | 2;
matching.js:161:24
161| declare const x: 1 | 2;
^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:193:14
Error ----------------------------------------------------------------------------------------------- matching.js:202:14

`match` is not exhaustively checked: object type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:193:14
193| const e2 = match (x) { // ERROR: `type: 'baz'` not checked
matching.js:202:14
202| const e2 = match (x) { // ERROR: `type: 'baz'` not checked
^^^^^

References:
matching.js:184:20
184| | {type: 'baz', val: boolean};
matching.js:193:20
193| | {type: 'baz', val: boolean};
^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:242:14
Error ----------------------------------------------------------------------------------------------- matching.js:251:14

`match` is not exhaustively checked: object type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:242:14
242| const e3 = match (x) { // ERROR: `type: 'bar', n: 2` not checked
matching.js:251:14
251| const e3 = match (x) { // ERROR: `type: 'bar', n: 2` not checked
^^^^^

References:
matching.js:227:20
227| | {type: 'bar', n: 2, val: boolean};
matching.js:236:20
236| | {type: 'bar', n: 2, val: boolean};
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:270:14
Error ----------------------------------------------------------------------------------------------- matching.js:279:14

`match` is not exhaustively checked: object type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:270:14
270| const e2 = match (x) { // ERROR: `type: 'bar'` not checked
matching.js:279:14
279| const e2 = match (x) { // ERROR: `type: 'bar'` not checked
^^^^^

References:
matching.js:262:20
262| | {type: 'bar', val: string}
matching.js:271:20
271| | {type: 'bar', val: string}
^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:288:14
Error ----------------------------------------------------------------------------------------------- matching.js:297:14

`match` is not exhaustively checked: tuple type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:288:14
288| const e2 = match (x) { // ERROR: `'baz'` element not checked
matching.js:297:14
297| const e2 = match (x) { // ERROR: `'baz'` element not checked
^^^^^

References:
matching.js:279:20
279| | ['baz', boolean];
matching.js:288:20
288| | ['baz', boolean];
^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:326:22
Error ----------------------------------------------------------------------------------------------- matching.js:335:22

Cannot cast `a` to empty because boolean [1] is incompatible with empty [2]. [incompatible-cast]

matching.js:326:22
326| [const a, _, _]: a as empty, // ERROR: `boolean` is not `empty`
matching.js:335:22
335| [const a, _, _]: a as empty, // ERROR: `boolean` is not `empty`
^

References:
matching.js:321:21
321| | [boolean, boolean, boolean];
matching.js:330:21
330| | [boolean, boolean, boolean];
^^^^^^^ [1]
matching.js:326:27
326| [const a, _, _]: a as empty, // ERROR: `boolean` is not `empty`
matching.js:335:27
335| [const a, _, _]: a as empty, // ERROR: `boolean` is not `empty`
^^^^^ [2]


Error ----------------------------------------------------------------------------------------------- matching.js:346:16
Error ----------------------------------------------------------------------------------------------- matching.js:355:16

Cannot cast `a` to string because number [1] is incompatible with string [2]. [incompatible-cast]

matching.js:346:16
346| [const a]: a as string, // ERROR: `number` is not `string`
matching.js:355:16
355| [const a]: a as string, // ERROR: `number` is not `string`
^

References:
matching.js:342:21
342| declare const x: [number] | Array<string>;
matching.js:351:21
351| declare const x: [number] | Array<string>;
^^^^^^ [1]
matching.js:346:21
346| [const a]: a as string, // ERROR: `number` is not `string`
matching.js:355:21
355| [const a]: a as string, // ERROR: `number` is not `string`
^^^^^^ [2]


Error ----------------------------------------------------------------------------------------------- matching.js:366:14
Error ----------------------------------------------------------------------------------------------- matching.js:375:14

`match` is not exhaustively checked: tuple type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:366:14
366| const e2 = match (x) { // ERROR: does not match all possibilities
matching.js:375:14
375| const e2 = match (x) { // ERROR: does not match all possibilities
^^^^^

References:
matching.js:359:20
359| declare const x: [a: 0, b?: 1, c?: 2];
matching.js:368:20
368| declare const x: [a: 0, b?: 1, c?: 2];
^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:370:14
Error ----------------------------------------------------------------------------------------------- matching.js:379:14

`match` is not exhaustively checked: tuple type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:370:14
370| const e3 = match (x) { // ERROR: does not match all possibilities
matching.js:379:14
379| const e3 = match (x) { // ERROR: does not match all possibilities
^^^^^

References:
matching.js:359:20
359| declare const x: [a: 0, b?: 1, c?: 2];
matching.js:368:20
368| declare const x: [a: 0, b?: 1, c?: 2];
^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:374:14
Error ----------------------------------------------------------------------------------------------- matching.js:383:14

`match` is not exhaustively checked: tuple type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:374:14
374| const e4 = match (x) { // ERROR: does not match all possibilities
matching.js:383:14
383| const e4 = match (x) { // ERROR: does not match all possibilities
^^^^^

References:
matching.js:359:20
359| declare const x: [a: 0, b?: 1, c?: 2];
matching.js:368:20
368| declare const x: [a: 0, b?: 1, c?: 2];
^^^^^^^^^^^^^^^^^^^^ [1]


Error ----------------------------------------------------------------------------------------------- matching.js:388:14
Error ----------------------------------------------------------------------------------------------- matching.js:397:14

`match` is not exhaustively checked: tuple type [1] has not been fully checked against by the match patterns below.
[match-not-exhaustive]

matching.js:388:14
388| const e2 = match (x) { // ERROR: does not match all elements
matching.js:397:14
397| const e2 = match (x) { // ERROR: does not match all elements
^^^^^

References:
matching.js:381:20
381| declare const x: [a: 0, ...];
matching.js:390:20
390| declare const x: [a: 0, ...];
^^^^^^^^^^^ [1]


Expand Down
9 changes: 9 additions & 0 deletions tests/match/matching.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,16 @@
const d: d as empty, // OK: all members checked
};
}
{
declare const x: {type: 'foo', value: 1}
| {type: 'bar', value: 2};

// Nested `as` pattern
const e1 = match (x) {
{type: 'foo' as a, const value}: (a as 'foo', value as 1), // OK
{type: 'bar' as a, const value}: (a as 'bar', value as 2), // OK
};
}

// Top level binding and wildcard
{
Expand Down
11 changes: 11 additions & 0 deletions tests/match/patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@
_: 0,
};
}
{
declare const x: {foo: {bar: number}};

const out = match (x) {
{foo: {bar: _} as const a}: 0, // OK
{foo: {bar: 1}}: 0, // OK
{foo: {bar: const a}}: 0, // OK
{foo: {bar: 1 as const a}}: 0, // OK
_: 0,
};
}

// Array rest
{
Expand Down

0 comments on commit 85e5e65

Please sign in to comment.