Skip to content

Commit b61e00f

Browse files
Pytype Teamrchen152
authored andcommitted
BEGIN_PUBLIC
Check compatibility of signatures for overriding methods. END_PUBLIC PiperOrigin-RevId: 444780409
1 parent e65c156 commit b61e00f

File tree

10 files changed

+1376
-9
lines changed

10 files changed

+1376
-9
lines changed

pytype/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,16 @@ py_library(
332332
pytype.pytd.pytd
333333
)
334334

335+
py_library(
336+
NAME
337+
overriding_checks
338+
SRCS
339+
overriding_checks.py
340+
DEPS
341+
pytype.abstract.abstract
342+
pytype.pytd.pytd
343+
)
344+
335345
py_library(
336346
NAME
337347
pytype_source_utils
@@ -428,6 +438,7 @@ py_library(
428438
._utils
429439
.blocks
430440
.metaclass
441+
.overriding_checks
431442
.state
432443
pytype.abstract.abstract
433444
pytype.pyc.pyc

pytype/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ def add_basic_options(o):
162162
"Enable support for nested classes in .py files."),
163163
("--strict-primitive-comparisons", False,
164164
"Emit errors for comparisons between incompatible primitive types."),
165+
("--overriding-default-value-checks", False,
166+
"Enable default value checks for overriding methods."),
167+
("--overriding-parameter-count-checks", False,
168+
"Enable parameter count checks for overriding methods."),
169+
("--overriding-parameter-name-checks", False,
170+
"Enable parameter name checks for overriding methods."),
171+
("--overriding-parameter-type-checks", False,
172+
"Enable parameter type checks for overriding methods."),
173+
("--overriding-return-type-checks", False,
174+
"Enable return type checks for overriding methods."),
165175
]
166176

167177

pytype/context.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
from pytype import vm_utils
1818
from pytype.abstract import abstract
1919
from pytype.abstract import abstract_utils
20+
from pytype.abstract import class_mixin
21+
from pytype.abstract import function
2022
from pytype.typegraph import cfg
2123
from pytype.typegraph import cfg_utils
2224

@@ -92,6 +94,10 @@ def __init__(
9294
# If set, allow construction of recursive values, setting the
9395
# self-referential field to Any
9496
self.recursion_allowed = False
97+
# Map from classes to maps from names of the instance methods
98+
# of the class to their signatures.
99+
self.method_signature_map: Dict[class_mixin.Class,
100+
Dict[str, function.Signature]] = {}
95101

96102
def matcher(self, node):
97103
return matcher.AbstractMatcher(node, self)

pytype/errors.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,27 @@ def overriding_final_attribute(self, stack, cls, base, name, details=None):
13641364
self._overriding_final(stack, cls, base, name, details=details,
13651365
is_method=False)
13661366

1367+
def _normalize_signature(self, signature):
1368+
"""If applicable, converts from `f(self: A, ...)` to `A.f(self, ...)`."""
1369+
self_name = signature.param_names[0]
1370+
if "." not in signature.name and self_name in signature.annotations:
1371+
annotations = dict(signature.annotations)
1372+
self_annot = annotations.pop(self_name)
1373+
signature = signature._replace(
1374+
name=f"{self_annot.full_name}.{signature.name}",
1375+
annotations=annotations)
1376+
return signature
1377+
1378+
@_error_name("signature-mismatch")
1379+
def overriding_signature_mismatch(self, stack, base_signature,
1380+
class_signature, details=None):
1381+
base_signature = self._normalize_signature(base_signature)
1382+
class_signature = self._normalize_signature(class_signature)
1383+
err_msg = (f"Overriding method signature mismatch.\n"
1384+
f"Base signature: '{base_signature}'.\n"
1385+
f"Subclass signature: '{class_signature}'.")
1386+
self.error(stack, err_msg, details=details)
1387+
13671388
@_error_name("final-error")
13681389
def assigning_to_final(self, stack, name, local):
13691390
"""Attempting to reassign a variable annotated with Final."""

0 commit comments

Comments
 (0)