Skip to content

Commit 51f990b

Browse files
committed
[mypyc] Fix is_native_ref_expr for class attrs.
1 parent 706a546 commit 51f990b

File tree

4 files changed

+127
-8
lines changed

4 files changed

+127
-8
lines changed

mypyc/irbuild/builder.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -979,17 +979,13 @@ def _analyze_iterable_item_type(self, expr: Expression) -> Type:
979979

980980
def is_native_module(self, module: str) -> bool:
981981
"""Is the given module one compiled by mypyc?"""
982-
return module in self.mapper.group_map
982+
return self.mapper.is_native_module(module)
983983

984984
def is_native_ref_expr(self, expr: RefExpr) -> bool:
985-
if expr.node is None:
986-
return False
987-
if "." in expr.node.fullname:
988-
return self.is_native_module(expr.node.fullname.rpartition(".")[0])
989-
return True
985+
return self.mapper.is_native_ref_expr(expr)
990986

991987
def is_native_module_ref_expr(self, expr: RefExpr) -> bool:
992-
return self.is_native_ref_expr(expr) and expr.kind == GDEF
988+
return self.mapper.is_native_module_ref_expr(expr)
993989

994990
def is_synthetic_type(self, typ: TypeInfo) -> bool:
995991
"""Is a type something other than just a class we've created?"""

mypyc/irbuild/mapper.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,12 @@ def is_native_ref_expr(self, expr: RefExpr) -> bool:
214214
if expr.node is None:
215215
return False
216216
if "." in expr.node.fullname:
217-
return self.is_native_module(expr.node.fullname.rpartition(".")[0])
217+
cur = expr.node.fullname
218+
while "." in cur:
219+
cur = cur.rpartition(".")[0]
220+
if self.is_native_module(cur):
221+
return True
222+
return False
218223
return True
219224

220225
def is_native_module_ref_expr(self, expr: RefExpr) -> bool:

mypyc/test-data/irbuild-classes.test

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,3 +1300,110 @@ class T:
13001300

13011301
class E(T):
13021302
y: str # E: Type of "y" is incompatible with definition in trait "T"
1303+
[case testClassBodyAttributeAccess_toplevel]
1304+
from typing import Final
1305+
1306+
class C:
1307+
a: Final = {'x': 'y'}
1308+
b: Final = a
1309+
[out]
1310+
def C.__mypyc_defaults_setup(__mypyc_self__):
1311+
__mypyc_self__ :: __main__.C
1312+
r0, r1 :: str
1313+
r2, r3 :: dict
1314+
r4 :: bool
1315+
L0:
1316+
r0 = 'x'
1317+
r1 = 'y'
1318+
r2 = CPyDict_Build(1, r0, r1)
1319+
__mypyc_self__.a = r2
1320+
r3 = __main__.C.a :: static
1321+
if is_error(r3) goto L1 else goto L2
1322+
L1:
1323+
r4 = raise NameError('value for final name "a" was not set')
1324+
unreachable
1325+
L2:
1326+
__mypyc_self__.b = r3
1327+
return 1
1328+
def __top_level__():
1329+
r0, r1 :: object
1330+
r2 :: bit
1331+
r3 :: str
1332+
r4, r5 :: object
1333+
r6 :: str
1334+
r7 :: dict
1335+
r8, r9 :: object
1336+
r10 :: str
1337+
r11, r12 :: object
1338+
r13 :: bool
1339+
r14, r15, r16 :: str
1340+
r17 :: tuple
1341+
r18 :: i32
1342+
r19 :: bit
1343+
r20 :: dict
1344+
r21 :: str
1345+
r22 :: i32
1346+
r23 :: bit
1347+
r24 :: object
1348+
r25, r26 :: str
1349+
r27 :: dict
1350+
r28 :: str
1351+
r29 :: i32
1352+
r30 :: bit
1353+
r31 :: object
1354+
r32 :: dict
1355+
r33 :: bool
1356+
r34 :: str
1357+
r35 :: i32
1358+
r36 :: bit
1359+
L0:
1360+
r0 = builtins :: module
1361+
r1 = load_address _Py_NoneStruct
1362+
r2 = r0 != r1
1363+
if r2 goto L2 else goto L1 :: bool
1364+
L1:
1365+
r3 = 'builtins'
1366+
r4 = PyImport_Import(r3)
1367+
builtins = r4 :: module
1368+
L2:
1369+
r5 = ('Final',)
1370+
r6 = 'typing'
1371+
r7 = __main__.globals :: static
1372+
r8 = CPyImport_ImportFromMany(r6, r5, r5, r7)
1373+
typing = r8 :: module
1374+
r9 = <error> :: object
1375+
r10 = '__main__'
1376+
r11 = __main__.C_template :: type
1377+
r12 = CPyType_FromTemplate(r11, r9, r10)
1378+
r13 = C_trait_vtable_setup()
1379+
r14 = '__mypyc_attrs__'
1380+
r15 = 'a'
1381+
r16 = 'b'
1382+
r17 = PyTuple_Pack(2, r15, r16)
1383+
r18 = PyObject_SetAttr(r12, r14, r17)
1384+
r19 = r18 >= 0 :: signed
1385+
__main__.C = r12 :: type
1386+
r20 = __main__.globals :: static
1387+
r21 = 'C'
1388+
r22 = CPyDict_SetItem(r20, r21, r12)
1389+
r23 = r22 >= 0 :: signed
1390+
r24 = __main__.C :: type
1391+
r25 = 'x'
1392+
r26 = 'y'
1393+
r27 = CPyDict_Build(1, r25, r26)
1394+
r28 = 'a'
1395+
r29 = PyObject_SetAttr(r24, r28, r27)
1396+
r30 = r29 >= 0 :: signed
1397+
__main__.C.a = r27 :: static
1398+
r31 = __main__.C :: type
1399+
r32 = __main__.C.a :: static
1400+
if is_error(r32) goto L3 else goto L4
1401+
L3:
1402+
r33 = raise NameError('value for final name "a" was not set')
1403+
unreachable
1404+
L4:
1405+
r34 = 'b'
1406+
r35 = PyObject_SetAttr(r31, r34, r32)
1407+
r36 = r35 >= 0 :: signed
1408+
__main__.C.b = r32 :: static
1409+
return 1

mypyc/test-data/run-classes.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,3 +2503,14 @@ class C:
25032503
def test_final_attribute() -> None:
25042504
assert C.A == -1
25052505
assert C.a == [-1]
2506+
[case testClassWithFinalAttributeAccess]
2507+
from typing import Final
2508+
2509+
class C:
2510+
a: Final = {'x': 'y'}
2511+
b: Final = C.a
2512+
2513+
def test_final_attribute() -> None:
2514+
assert C.a['x'] == 'y'
2515+
assert C.b['x'] == 'y'
2516+
assert C.a is C.b

0 commit comments

Comments
 (0)