@@ -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