Skip to content

Commit 90b2b7d

Browse files
SamChou19815meta-codesync[bot]
authored andcommitted
[flow][refactor] Type check match_pattern in env_resolution
Summary: In this diff, we now run type checking for match patterns in env_resolution, and the result will be stored in node_cache. This will enable us to check exhaustiveness during inference, to make [this example](https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+h46fNRLuKxJIGWh8MeT0ZfhYlCStpHzNsFBAMIQkIEQwJODAQfiEyfBE4eWw2fDgofDBMsAALfAA3KjgsXGxxZC4eAw0G-GhcWn9aY3wWZldu-g1mbGqJUoBaCRHEzrcDEgBrbAk62kXhXFxJ923d-cPRHEpTgyEoMDaqZdW7vKgoOfaSKgOKpqmDA+d4gB5fMA-P6LCCMLLQbiLOoYCqgh6-GDYRYIXYLSgkRZkCR4jpddwPfJLZjpOBkUEKTwJEJ+DAkMiUFSwkyZCC3dbdAC+-EgGiSGieVGwAAJbPYpfJkFKANoARilAB8pQAmAC6AG4ADpQI2yiRSiCpKUAXilGT2tSlAAp5ABKKXAI1Sr3KlU660APilAAZeJ7vUrTVKMH6rYGMFGSNrQ1ABXrciAGiYSHBoEkGkGrFqAOwAVisQZAAqAA) type check. Changelog: [internal] Reviewed By: panagosg7 Differential Revision: D85289492 fbshipit-source-id: 8ec47a4cbe3b885ad7f7ba90d9626cd2c1dc7788
1 parent feb0a0d commit 90b2b7d

8 files changed

Lines changed: 66 additions & 42 deletions

File tree

src/analysis/env_builder/name_def.ml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3270,7 +3270,11 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope =
32703270
~f:(fun i prev_pattern_locs_rev (_, { Case.pattern; body; guard; case_match_root_loc; _ })
32713271
->
32723272
let acc = MatchCaseRoot { case_match_root_loc; prev_pattern_locs_rev } in
3273-
this#add_match_destructure_bindings ~case_match_root_loc acc pattern;
3273+
this#add_match_destructure_bindings
3274+
~case_match_root_loc
3275+
~has_guard:(Option.is_some guard)
3276+
acc
3277+
pattern;
32743278
ignore @@ super#match_pattern pattern;
32753279
Base.Option.iter guard ~f:(this#visit_expression ~hints:[] ~cond:OtherTestContext);
32763280
(* We use best-effort value hints for cases other than the current case.
@@ -3298,7 +3302,11 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope =
32983302
~f:(fun prev_pattern_locs_rev (_, { Case.pattern; body; guard; case_match_root_loc; _ })
32993303
->
33003304
let acc = MatchCaseRoot { case_match_root_loc; prev_pattern_locs_rev } in
3301-
this#add_match_destructure_bindings ~case_match_root_loc acc pattern;
3305+
this#add_match_destructure_bindings
3306+
~case_match_root_loc
3307+
~has_guard:(Option.is_some guard)
3308+
acc
3309+
pattern;
33023310
ignore @@ super#match_pattern pattern;
33033311
Base.Option.iter guard ~f:(this#visit_expression ~hints:[] ~cond:OtherTestContext);
33043312
run this#statement body;
@@ -3307,7 +3315,7 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope =
33073315
in
33083316
x
33093317

3310-
method add_match_destructure_bindings ~case_match_root_loc root pattern =
3318+
method add_match_destructure_bindings ~case_match_root_loc ~has_guard root pattern =
33113319
let visit_binding loc name binding =
33123320
let binding = this#mk_hooklike_if_necessary (Flow_ast_utils.hook_name name) binding in
33133321
this#add_ordinary_binding
@@ -3319,7 +3327,7 @@ class def_finder ~autocomplete_hooks ~react_jsx env_info toplevel_scope =
33193327
this#add_binding
33203328
(Env_api.MatchCasePatternLoc, pattern_loc)
33213329
(mk_reason RMatchPattern pattern_loc)
3322-
(MatchCasePattern { case_match_root_loc; pattern });
3330+
(MatchCasePattern { case_match_root_loc; has_guard; pattern });
33233331
MatchPattern.visit_pattern
33243332
~visit_binding
33253333
~visit_expression:(this#visit_expression ~hints:[] ~cond:MatchPattern)

src/analysis/env_builder/name_def_ordering.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ struct
11881188
in
11891189
function
11901190
| Binding binding -> depends_of_binding binding
1191-
| MatchCasePattern { case_match_root_loc; pattern } ->
1191+
| MatchCasePattern { case_match_root_loc; has_guard = _; pattern } ->
11921192
depends_on_match_pattern case_match_root_loc pattern EnvMap.empty
11931193
| ExpressionDef { expr; hints; _ } ->
11941194
depends_of_hinted_expression ~for_expression_writes:true hints expr EnvMap.empty

src/analysis/env_builder/name_def_types.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ type def =
169169
| Binding of binding
170170
| MatchCasePattern of {
171171
case_match_root_loc: ALoc.t;
172+
has_guard: bool;
172173
pattern: (ALoc.t, ALoc.t) Ast.MatchPattern.t;
173174
}
174175
| ExpressionDef of expression_def

src/typing/env_resolution.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,10 @@ let resolve_chain_expression cx ~cond exp =
10721072

10731073
let resolve_write_expression cx ~cond exp = synthesizable_expression cx ~encl_ctx:cond exp
10741074

1075-
let resolve_match_pattern cx def_scope_kind def_reason case_match_root_loc pattern =
1076-
ignore (cx, def_scope_kind, def_reason, case_match_root_loc, pattern);
1075+
let resolve_match_pattern cx def_reason case_match_root_loc ~has_guard pattern =
1076+
let (_pattern : (ALoc.t, ALoc.t * Type.t) Ast.MatchPattern.t) =
1077+
Statement.match_pattern cx case_match_root_loc ~has_guard pattern
1078+
in
10771079
MixedT.why def_reason
10781080

10791081
let resolve_generator_next cx reason gen =
@@ -1116,8 +1118,8 @@ let resolve cx (def_kind, id_loc) (def, def_scope_kind, class_stack, def_reason)
11161118
let t =
11171119
match def with
11181120
| Binding b -> resolve_binding cx def_scope_kind def_reason id_loc b
1119-
| MatchCasePattern { case_match_root_loc; pattern } ->
1120-
resolve_match_pattern cx def_scope_kind def_reason case_match_root_loc pattern
1121+
| MatchCasePattern { case_match_root_loc; has_guard; pattern } ->
1122+
resolve_match_pattern cx def_reason case_match_root_loc ~has_guard pattern
11211123
| ExpressionDef { cond_context = cond; expr; chain = true; hints = _ } ->
11221124
resolve_chain_expression cx ~cond expr
11231125
| ExpressionDef { cond_context = cond; expr; chain = false; hints = _ } ->

src/typing/node_cache.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type cache = {
5050
)
5151
)
5252
ALocMap.t;
53+
match_patterns: ((ALoc.t, ALoc.t * Type.t) Ast.MatchPattern.t * bool) ALocMap.t;
5354
}
5455

5556
type t = cache ref
@@ -73,6 +74,7 @@ let mk_empty () =
7374
class_sigs = ALocMap.empty;
7475
tparams = ALocMap.empty;
7576
component_sigs = ALocMap.empty;
77+
match_patterns = ALocMap.empty;
7678
}
7779

7880
let set_annotation cache ((loc, _) as anno) =
@@ -124,6 +126,9 @@ let set_tparam cache (((loc, _), _, _) as param) =
124126
let set_component_sig cache loc c =
125127
cache := { !cache with component_sigs = ALocMap.add loc c !cache.component_sigs }
126128

129+
let set_match_pattern cache loc p =
130+
cache := { !cache with match_patterns = ALocMap.add loc p !cache.match_patterns }
131+
127132
let get_annotation cache loc = ALocMap.find_opt loc !cache.annotations
128133

129134
let get_expression cache loc = ALocMap.find_opt loc !cache.expressions
@@ -155,3 +160,5 @@ let get_class_sig cache loc = ALocMap.find_opt loc !cache.class_sigs
155160
let get_tparam cache loc = ALocMap.find_opt loc !cache.tparams
156161

157162
let get_component_sig cache loc = ALocMap.find_opt loc !cache.component_sigs
163+
164+
let get_match_pattern cache loc = ALocMap.find_opt loc !cache.match_patterns

src/typing/node_cache.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ val set_component_sig :
7777
) ->
7878
unit
7979

80+
val set_match_pattern : t -> ALoc.t -> (ALoc.t, ALoc.t * Type.t) Ast.MatchPattern.t * bool -> unit
81+
8082
val get_annotation : t -> ALoc.t -> (ALoc.t, ALoc.t * Type.t) Ast.Type.annotation option
8183

8284
val get_expression : t -> ALoc.t -> (ALoc.t, ALoc.t * Type.t) Ast.Expression.t option
@@ -145,3 +147,5 @@ val get_component_sig :
145147
)
146148
)
147149
option
150+
151+
val get_match_pattern : t -> ALoc.t -> ((ALoc.t, ALoc.t * Type.t) Ast.MatchPattern.t * bool) option

src/typing/statement.ml

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,23 +1339,7 @@ module Make
13391339
case
13401340
in
13411341
let pattern =
1342-
Match_pattern.pattern
1343-
cx
1344-
( case_match_root_loc,
1345-
Flow_ast.Expression.Identifier
1346-
(Flow_ast_utils.match_root_ident case_match_root_loc)
1347-
)
1348-
pattern
1349-
~on_identifier:(fun ~encl_ctx cx ->
1350-
identifier cx { empty_syntactic_flags with Natural_inference.encl_ctx })
1351-
~on_expression:expression
1352-
~on_binding:(fun ~use_op ~name_loc ~kind name t ->
1353-
init_var kind cx ~use_op t name_loc;
1354-
Type_env.constraining_type
1355-
~default:(Type_env.get_var_declared_type cx (OrdinaryName name) name_loc)
1356-
cx
1357-
name
1358-
name_loc)
1342+
match_pattern cx case_match_root_loc ~has_guard:(Option.is_some guard) pattern
13591343
in
13601344
let guard = Base.Option.map ~f:(expression cx) guard in
13611345
(match body with
@@ -3129,22 +3113,7 @@ module Make
31293113
case
31303114
in
31313115
let pattern =
3132-
Match_pattern.pattern
3133-
cx
3134-
( case_match_root_loc,
3135-
Identifier (Flow_ast_utils.match_root_ident case_match_root_loc)
3136-
)
3137-
pattern
3138-
~on_identifier:(fun ~encl_ctx cx ->
3139-
identifier cx { empty_syntactic_flags with Natural_inference.encl_ctx })
3140-
~on_expression:expression
3141-
~on_binding:(fun ~use_op ~name_loc ~kind name t ->
3142-
init_var kind cx ~use_op t name_loc;
3143-
Type_env.constraining_type
3144-
~default:(Type_env.get_var_declared_type cx (OrdinaryName name) name_loc)
3145-
cx
3146-
name
3147-
name_loc)
3116+
match_pattern cx case_match_root_loc ~has_guard:(Option.is_some guard) pattern
31483117
in
31493118
let (guard, guard_throws) =
31503119
match guard with
@@ -9014,6 +8983,32 @@ module Make
90148983
in
90158984
{ enum_name; enum_id; members; representation_t; has_unknown_members }
90168985

8986+
and match_pattern cx case_match_root_loc ~has_guard pattern =
8987+
let node_cache = Context.node_cache cx in
8988+
match Node_cache.get_match_pattern node_cache (fst pattern) with
8989+
| Some (p, _has_guard) -> p
8990+
| None ->
8991+
let p =
8992+
Match_pattern.pattern
8993+
cx
8994+
( case_match_root_loc,
8995+
Flow_ast.Expression.Identifier (Flow_ast_utils.match_root_ident case_match_root_loc)
8996+
)
8997+
pattern
8998+
~on_identifier:(fun ~encl_ctx cx ->
8999+
identifier cx { empty_syntactic_flags with Natural_inference.encl_ctx })
9000+
~on_expression:expression
9001+
~on_binding:(fun ~use_op ~name_loc ~kind name t ->
9002+
init_var kind cx ~use_op t name_loc;
9003+
Type_env.constraining_type
9004+
~default:(Type_env.get_var_declared_type cx (OrdinaryName name) name_loc)
9005+
cx
9006+
name
9007+
name_loc)
9008+
in
9009+
Node_cache.set_match_pattern node_cache (fst pattern) (p, has_guard);
9010+
p
9011+
90179012
and error_on_match_case_invalid_syntax
90189013
cx ~match_keyword_loc (invalid_syntax_list : ALoc.t Flow_ast.Match.Case.InvalidSyntax.t list)
90199014
: unit =

src/typing/statement_sig.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,11 @@ module type S = sig
276276
Type.t
277277

278278
val empty_array : Context.t -> ALoc.t -> Reason.t * Type.t
279+
280+
val match_pattern :
281+
Context.t ->
282+
ALoc.t ->
283+
has_guard:bool ->
284+
(ALoc.t, ALoc.t) Ast.MatchPattern.t ->
285+
(ALoc.t, ALoc.t * Type.t) Ast.MatchPattern.t
279286
end

0 commit comments

Comments
 (0)