Skip to content

Commit 7e8666c

Browse files
shannonzhufacebook-github-bot
authored andcommitted
Add more detailed temporary refinement unit tests
Reviewed By: grievejia Differential Revision: D30430527 fbshipit-source-id: 51a77f6460176e19f26605b90b592f6dd86ed7be
1 parent 2102bad commit 7e8666c

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

source/analysis/test/integration/refinementTest.ml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,153 @@ let test_check_temporary_refinement context =
11741174
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
11751175
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
11761176
];
1177+
assert_type_errors
1178+
{|
1179+
from typing import Optional
1180+
1181+
class Foo:
1182+
attribute: Optional[int] = 1
1183+
1184+
class Bar:
1185+
def unrelated_call(self) -> None:
1186+
pass
1187+
1188+
def test(foo: Foo) -> None:
1189+
reveal_type(foo.attribute)
1190+
foo.attribute = 1
1191+
reveal_type(foo.attribute)
1192+
bar = Bar()
1193+
reveal_type(foo.attribute)
1194+
if not foo.attribute:
1195+
return
1196+
reveal_type(foo.attribute)
1197+
bar.unrelated_call()
1198+
reveal_type(foo.attribute)
1199+
|}
1200+
[
1201+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1202+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]` (inferred: \
1203+
`typing_extensions.Literal[1]`).";
1204+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1205+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]` (inferred: `int`).";
1206+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1207+
];
1208+
assert_type_errors
1209+
{|
1210+
from typing import Optional
1211+
1212+
class Foo:
1213+
attribute: Optional[int] = 1
1214+
1215+
def interleaving_call() -> None: pass
1216+
1217+
def test(foo: Foo) -> None:
1218+
reveal_type(foo.attribute)
1219+
if not foo.attribute:
1220+
return
1221+
local_copy = foo.attribute
1222+
interleaving_call()
1223+
reveal_type(foo.attribute)
1224+
reveal_type(local_copy)
1225+
|}
1226+
[
1227+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1228+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1229+
"Revealed type [-1]: Revealed type for `local_copy` is `int`.";
1230+
];
1231+
assert_type_errors
1232+
{|
1233+
from typing import Optional
1234+
1235+
class Foo:
1236+
attribute: Optional[int] = 1
1237+
1238+
class Bar:
1239+
foo: Optional[Foo] = Foo()
1240+
1241+
def interleaving_call() -> None: pass
1242+
1243+
def test(bar: Bar) -> None:
1244+
if bar.foo.attribute is not None:
1245+
return
1246+
reveal_type(bar.foo)
1247+
reveal_type(bar.foo.attribute)
1248+
1249+
if bar.foo and bar.foo.attribute:
1250+
reveal_type(bar.foo.attribute)
1251+
|}
1252+
[
1253+
"Undefined attribute [16]: `Optional` has no attribute `attribute`.";
1254+
"Revealed type [-1]: Revealed type for `bar.foo` is `Optional[Foo]`.";
1255+
"Revealed type [-1]: Revealed type for `bar.foo.attribute` is `unknown`.";
1256+
"Revealed type [-1]: Revealed type for `bar.foo.attribute` is `Optional[int]` (inferred: \
1257+
`int`).";
1258+
];
1259+
(* TODO(T98646613): Refinement should not stick here. *)
1260+
assert_type_errors
1261+
{|
1262+
from typing import Optional
1263+
1264+
class Foo:
1265+
attribute: Optional[int] = 1
1266+
1267+
def interleaving_call() -> None: pass
1268+
1269+
def test(foo: Foo) -> None:
1270+
if not foo.attribute:
1271+
return interleaving_call()
1272+
reveal_type(foo.attribute)
1273+
|}
1274+
["Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]` (inferred: `int`)."];
1275+
assert_type_errors
1276+
{|
1277+
from typing import Optional
1278+
1279+
class Foo:
1280+
attribute: Optional[int] = 1
1281+
1282+
class Bar:
1283+
attribute: Optional[int] = 1
1284+
1285+
def interleaving_call() -> None:
1286+
pass
1287+
1288+
def test(foo: Foo, bar: Bar) -> None:
1289+
if not foo.attribute or not bar.attribute:
1290+
return
1291+
reveal_type(foo.attribute)
1292+
reveal_type(bar.attribute)
1293+
1294+
interleaving_call()
1295+
1296+
if not foo.attribute and not bar.attribute:
1297+
return
1298+
reveal_type(foo.attribute)
1299+
reveal_type(bar.attribute)
1300+
|}
1301+
[
1302+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]` (inferred: `int`).";
1303+
"Revealed type [-1]: Revealed type for `bar.attribute` is `Optional[int]` (inferred: `int`).";
1304+
"Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]`.";
1305+
"Revealed type [-1]: Revealed type for `bar.attribute` is `Optional[int]`.";
1306+
];
1307+
(* TODO(T98646613): Refinement should not stick here. *)
1308+
assert_type_errors
1309+
{|
1310+
from typing import Optional
1311+
1312+
class Foo:
1313+
attribute: Optional[int] = 1
1314+
1315+
def interleaving_call() -> None:
1316+
pass
1317+
1318+
def test(foo: Foo) -> None:
1319+
if not foo.attribute or interleaving_call():
1320+
return
1321+
reveal_type(foo.attribute)
1322+
|}
1323+
["Revealed type [-1]: Revealed type for `foo.attribute` is `Optional[int]` (inferred: `int`)."];
11771324
()
11781325

11791326

0 commit comments

Comments
 (0)