Skip to content

Commit 4c77d16

Browse files
authored
[mypyc] Don't make classes non-extension because of children (python#7988)
This is a global behavior that will be solidly busted when doing separate compilation. Produce an error instead. (We can probably support it once we support interpreted inheritance.)
1 parent b96d4d0 commit 4c77d16

File tree

3 files changed

+14
-37
lines changed

3 files changed

+14
-37
lines changed

mypyc/genops.py

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,12 @@ def build_type_map(mapper: 'Mapper',
134134
for module, cdef in classes:
135135
class_ir = ClassIR(cdef.name, module.fullname, is_trait(cdef),
136136
is_abstract=cdef.info.is_abstract)
137+
class_ir.is_ext_class = is_extension_class(cdef)
137138
# If global optimizations are disabled, turn of tracking of class children
138139
if not options.global_opts:
139140
class_ir.children = None
140141
mapper.type_to_ir[cdef.info] = class_ir
141142

142-
# Figure out which classes need to be compiled as non-extension classes.
143-
mark_non_ext_classes(mapper.type_to_ir)
144-
145143
# Populate structural information in class IR for extension classes.
146144
for module, cdef in classes:
147145
with catch_errors(module.path, cdef.line):
@@ -250,39 +248,6 @@ def is_extension_class(cdef: ClassDef) -> bool:
250248
return True
251249

252250

253-
def mark_non_ext_classes(class_map: Dict[TypeInfo, ClassIR]) -> None:
254-
"""
255-
Mark which classes should be compiled as non-extension classes.
256-
Classes in the chain of base classes of a non-extension class
257-
will all be marked as non-extension because currently
258-
non-extension classes cannot inherit from extension classes.
259-
"""
260-
visit_first = list(class_map.keys())
261-
visit_second = [] # type: List[TypeInfo]
262-
# First pass to gather all non-extension classes without
263-
# considering base class chains
264-
for typ in visit_first:
265-
ir = class_map[typ]
266-
ir.is_ext_class = is_extension_class(typ.defn)
267-
if not ir.is_ext_class:
268-
visit_second.append(typ)
269-
270-
# FIXME: Just reject these?
271-
# Second pass to propagate non-extension markings up the base class
272-
# chains of classes marked as non-extension classes during the first pass.
273-
for typ in visit_second:
274-
todo = [typ]
275-
while todo:
276-
child = todo.pop()
277-
for parent in child.bases:
278-
if parent.type in class_map:
279-
parent_ir = class_map[parent.type]
280-
if not parent_ir.is_ext_class:
281-
continue
282-
parent_ir.is_ext_class = False
283-
todo.append(parent.type)
284-
285-
286251
def get_func_def(op: Union[FuncDef, Decorator, OverloadedFuncDef]) -> FuncDef:
287252
if isinstance(op, OverloadedFuncDef):
288253
assert op.impl
@@ -699,9 +664,15 @@ def prepare_non_ext_class_def(path: str, module_name: str, cdef: ClassDef,
699664
path, cdef.line)
700665
# Handle case for regular function overload
701666
else:
702-
errors.error("Non-extension classes do not support overlaoded functions",
667+
errors.error("Non-extension classes do not support overloaded functions",
703668
path, cdef.line)
704669

670+
if any(
671+
cls in mapper.type_to_ir and mapper.type_to_ir[cls].is_ext_class for cls in info.mro
672+
):
673+
errors.error(
674+
"Non-extension classes may not inherit from extension classes", path, cdef.line)
675+
705676

706677
def concrete_arg_kind(kind: int) -> int:
707678
"""Find the concrete version of an arg kind that is being passed."""

mypyc/test-data/commandline.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class Concrete2:
148148
class Trait2(Concrete2):
149149
pass
150150

151+
@decorator
152+
class NonExt(Concrete1): # E: Non-extension classes may not inherit from extension classes
153+
pass
154+
151155
class Nope(Trait1, Concrete2): # E: Non-trait bases must appear first in parent list # E: Non-trait MRO must be linear
152156
pass
153157

mypyc/test-data/run-classes.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@ from typing import Any
6363
def decorator(cls) -> Any:
6464
return cls
6565

66+
@decorator
6667
class C:
6768
def __init__(self) -> None:
6869
self.c = 3
6970

7071
def get_c(self) -> int:
7172
return self.c
7273

74+
@decorator
7375
class B(C):
7476
def __init__(self) -> None:
7577
super().__init__()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy