Skip to content

Commit

Permalink
improve refinement for match
Browse files Browse the repository at this point in the history
Summary:
When we generate conditions on an index of a sequence, if the sequence is a tuple literal and the index is in-bounds, we can generate the condition on the appropriate sub-expression within the tuple literal, instead of synthesizing a new subscript expression.

One gap that I discovered but didn't fix with this diff is for MatchAs, for example `match subject: case (1, 2) as z:`, which does not give the correct type to z. This is because for MatchAs we generate two refinement conditions, `z == subject && z == (1, 2)`, where `subject: tuple[object, object]`. To combine the refinements we `meet` the two types, and the result is `tuple[object, object]`, even though `tuple[1, 2]` is narrower. I think the desired behavior should be intersection, but probably not worth doing in pyre1.

Reviewed By: stroxler

Differential Revision: D68169119

fbshipit-source-id: 4d2867ec91414dcc8b1801739fca3d5179c1ea56
  • Loading branch information
yangdanny97 authored and facebook-github-bot committed Jan 14, 2025
1 parent 2ee42a9 commit 28a3c35
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
13 changes: 9 additions & 4 deletions source/analysis/cfg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,15 @@ module MatchTranslate = struct


let create_subscript_index ~location ~sequence ~index =
create_subscript
~location
~container:sequence
~key:(create_constant ~location (Constant.Integer index))
match sequence with
| { Node.value = Expression.Tuple elements; _ } when index >= 0 && index < List.length elements
->
List.nth_exn elements index
| _ ->
create_subscript
~location
~container:sequence
~key:(create_constant ~location (Constant.Integer index))


let create_call ~location ~callee ~arguments =
Expand Down
18 changes: 18 additions & 0 deletions source/analysis/test/integration/matchTest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ let test_simple =
test_list
[
labeled_test_case __FUNCTION__ __LINE__
@@ assert_type_errors
{|
def foo(x: object, y: object) -> None:
match (x, y):
case (1, 2):
reveal_type(x)
reveal_type(y)
case (1 as x2, 2 as y2):
reveal_type(x2)
reveal_type(y2)
|}
[
"Revealed type [-1]: Revealed type for `x` is `typing_extensions.Literal[1]`.";
"Revealed type [-1]: Revealed type for `y` is `typing_extensions.Literal[2]`.";
"Revealed type [-1]: Revealed type for `x2` is `typing_extensions.Literal[1]`.";
"Revealed type [-1]: Revealed type for `y2` is `typing_extensions.Literal[2]`.";
];
labeled_test_case __FUNCTION__ __LINE__
@@ assert_type_errors
{|
def foo(x: int) -> None:
Expand Down

0 comments on commit 28a3c35

Please sign in to comment.