-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[flow][match] Propagate hints through match expressions case bodies
Summary: We need to propagate hints through match expressions case bodies. The simple case is when we have some external hint. More interesting is getting hints from sibling case bodies. This can come out of order, and indeed this might be a common pattern with match expressions as people like to list their edge cases first. E.g. ``` declare const x: number; const out = match (x) { 0: [], const x: [x], }; ``` So, we consider every sibling case body, from top to bottom, as a "best effort hint". The logic for hints diverges the match statement and match expression logic, so I break these up again into seperate methods. Changelog: [internal] Reviewed By: panagosg7 Differential Revision: D70140524 fbshipit-source-id: 499d5e8864964c32c6bce372743dec2adb4781cf
- Loading branch information
1 parent
b55e5c3
commit c313dc3
Showing
2 changed files
with
133 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Annotation hint | ||
type F = string => boolean; | ||
{ | ||
declare const x: 'a'; | ||
|
||
const out: F = match (x) { | ||
'a': y => true, // OK | ||
}; | ||
} | ||
|
||
// Sibling before | ||
{ | ||
declare const x: 'a' | 'b'; | ||
|
||
const out = match (x) { | ||
'a': [1], | ||
'b': [], // Should be `Array<number>` | ||
}; | ||
out as Array<number>; // OK | ||
} | ||
|
||
// Sibling after | ||
{ | ||
declare const x: 'a' | 'b'; | ||
|
||
const out = match (x) { | ||
'a': [], // Should be `Array<number>` | ||
'b': [1], | ||
}; | ||
out as Array<number>; // OK | ||
} | ||
|
||
// Multiple siblings, one valid | ||
{ | ||
declare const x: 'a' | 'b' | 'c' | 'd'; | ||
|
||
const out = match (x) { | ||
'a': 1, | ||
'b': {}, | ||
'c': [1], | ||
'd': [], // Should be `Array<number>` | ||
}; | ||
out as number | {} | Array<number>; // OK | ||
} | ||
|
||
// Multiple siblings, multiple valid | ||
{ | ||
declare const x: 'a' | 'b' | 'c'; | ||
|
||
const out = match (x) { | ||
'a': [true], | ||
'b': [1], | ||
'c': [], | ||
}; | ||
out as Array<boolean> | Array<number>; // OK | ||
} | ||
{ | ||
declare const x: 'a' | 'b' | 'c'; | ||
|
||
const out = match (x) { | ||
'a': (x: number) => 1, | ||
'b': (x: string) => true, | ||
'c': x => x as number, // OK | ||
}; | ||
} | ||
|
||
// Cycles avoided | ||
{ | ||
declare const x: 'a' | 'b'; | ||
|
||
const out: (x: number) => void = match (x) { // OK | ||
'a': (x) => {}, | ||
'b': (x) => {}, | ||
}; | ||
} | ||
{ | ||
declare const x: 'a' | 'b'; | ||
|
||
const out: Array<number> = match (x) { // OK | ||
'a': [], | ||
'b': [], | ||
}; | ||
} |