Skip to content

Commit

Permalink
add test for wrong use of @OverRide with overload
Browse files Browse the repository at this point in the history
  • Loading branch information
carljm committed Jan 10, 2025
1 parent f4cb435 commit 60f9f81
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 46 deletions.
46 changes: 27 additions & 19 deletions conformance/results/mypy/overloads_invalid.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Does not allow an overload with no implementation in an abstract base class.
"""
errors_diff = """
Line 49: Unexpected errors ['overloads_invalid.py:49: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]']
Line 199: Unexpected errors ['overloads_invalid.py:199: error: Signature of "good_override" incompatible with supertype "Base" [override]']
Line 202: Unexpected errors ['overloads_invalid.py:202: error: Signature of "good_override" incompatible with supertype "Base" [override]']
"""
output = """
overloads_invalid.py:14: error: Single overload definition, multiple required [misc]
Expand All @@ -18,22 +18,30 @@ overloads_invalid.py:88: error: Overloaded function implementation does not acce
overloads_invalid.py:91: error: Overload does not consistently use the "@classmethod" decorator on all function signatures. [misc]
overloads_invalid.py:133: error: @final should be applied only to overload implementation [misc]
overloads_invalid.py:148: error: @final should be applied only to overload implementation [misc]
overloads_invalid.py:173: error: Cannot override final attribute "final_method" (previously declared in base class "Base") [misc]
overloads_invalid.py:173: error: Signature of "final_method" incompatible with supertype "Base" [override]
overloads_invalid.py:173: note: Superclass:
overloads_invalid.py:173: note: @overload
overloads_invalid.py:173: note: def final_method(self, x: int) -> int
overloads_invalid.py:173: note: @overload
overloads_invalid.py:173: note: def final_method(self, x: str) -> str
overloads_invalid.py:173: note: Subclass:
overloads_invalid.py:173: note: def final_method(self, x: int | str) -> int | str
overloads_invalid.py:180: error: Method "bad_override" is marked as an override, but no base method was found with this name [misc]
overloads_invalid.py:199: error: Signature of "good_override" incompatible with supertype "Base" [override]
overloads_invalid.py:199: note: Superclass:
overloads_invalid.py:199: note: def good_override(self, x: int | str) -> int | str
overloads_invalid.py:199: note: Subclass:
overloads_invalid.py:199: note: @overload
overloads_invalid.py:199: note: def good_override(self, x: int) -> int
overloads_invalid.py:199: note: @overload
overloads_invalid.py:199: note: def good_override(self, x: str) -> str
overloads_invalid.py:176: error: Cannot override final attribute "final_method" (previously declared in base class "Base") [misc]
overloads_invalid.py:176: error: Signature of "final_method" incompatible with supertype "Base" [override]
overloads_invalid.py:176: note: Superclass:
overloads_invalid.py:176: note: @overload
overloads_invalid.py:176: note: def final_method(self, x: int) -> int
overloads_invalid.py:176: note: @overload
overloads_invalid.py:176: note: def final_method(self, x: str) -> str
overloads_invalid.py:176: note: Subclass:
overloads_invalid.py:176: note: def final_method(self, x: int | str) -> int | str
overloads_invalid.py:183: error: Method "bad_override" is marked as an override, but no base method was found with this name [misc]
overloads_invalid.py:202: error: Signature of "good_override" incompatible with supertype "Base" [override]
overloads_invalid.py:202: note: Superclass:
overloads_invalid.py:202: note: def good_override(self, x: int | str) -> int | str
overloads_invalid.py:202: note: Subclass:
overloads_invalid.py:202: note: @overload
overloads_invalid.py:202: note: def good_override(self, x: int) -> int
overloads_invalid.py:202: note: @overload
overloads_invalid.py:202: note: def good_override(self, x: str) -> str
overloads_invalid.py:217: error: Signature of "to_override" incompatible with supertype "Base" [override]
overloads_invalid.py:217: note: Superclass:
overloads_invalid.py:217: note: def to_override(self, x: int | str) -> int | str
overloads_invalid.py:217: note: Subclass:
overloads_invalid.py:217: note: @overload
overloads_invalid.py:217: note: def to_override(self, x: int) -> int
overloads_invalid.py:217: note: @overload
overloads_invalid.py:217: note: def to_override(self, x: str) -> str
"""
11 changes: 6 additions & 5 deletions conformance/results/pyre/overloads_invalid.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ Does not allow an overload with no implementation in a Protocol or an abstract b
Expects @final/@override on all overloads and implementation, instead of implementation only.
"""
errors_diff = """
Line 217: Expected 1 errors
Lines 148, 150: Expected error (tag 'invalid_final_2')
Line 40: Unexpected errors ['overloads_invalid.py:40:4 Missing overload implementation [42]: Overloaded function `MyProto.func3` must have an implementation.']
Line 51: Unexpected errors ['overloads_invalid.py:51:4 Missing overload implementation [42]: Overloaded function `MyAbstractBase.func4` must have an implementation.']
Line 128: Unexpected errors ['overloads_invalid.py:128:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 208: Unexpected errors ['overloads_invalid.py:208:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
Line 211: Unexpected errors ['overloads_invalid.py:211:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
"""
output = """
overloads_invalid.py:15:0 Incompatible overload [43]: At least two overload signatures must be present.
Expand All @@ -24,8 +25,8 @@ overloads_invalid.py:97:4 Incompatible overload [43]: The implementation of `C.f
overloads_invalid.py:97:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:128:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:139:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:173:4 Invalid override [40]: `overloads_invalid.Child.final_method` cannot override final method defined in `Base`.
overloads_invalid.py:189:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:189:4 Invalid override [40]: `overloads_invalid.Child.bad_override` is decorated with @override, but no method of the same name exists in superclasses of `Child`.
overloads_invalid.py:208:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:176:4 Invalid override [40]: `overloads_invalid.Child.final_method` cannot override final method defined in `Base`.
overloads_invalid.py:192:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
overloads_invalid.py:192:4 Invalid override [40]: `overloads_invalid.Child.bad_override` is decorated with @override, but no method of the same name exists in superclasses of `Child`.
overloads_invalid.py:211:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
"""
9 changes: 5 additions & 4 deletions conformance/results/pyright/overloads_invalid.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
conformant = "Partial"
notes = """
Allows @final on all overloads and implementation; should be implementation-only.
Allows @final/@override on all overloads and implementation; should be implementation-only.
"""
conformance_automated = "Fail"
errors_diff = """
Line 217: Expected 1 errors
Lines 148, 150: Expected error (tag 'invalid_final_2')
"""
output = """
Expand All @@ -26,10 +27,10 @@ overloads_invalid.py:88:9 - error: Overloaded implementation is not consistent w
overloads_invalid.py:93:9 - error: Overloads for "func6" use @classmethod inconsistently (reportInconsistentOverload)
overloads_invalid.py:97:15 - warning: Instance methods should take a "self" parameter (reportSelfClsParameterName)
overloads_invalid.py:135:9 - error: Overload for "invalid_final" is marked @final but implementation is not (reportInconsistentOverload)
overloads_invalid.py:173:9 - error: Method "final_method" cannot override final method defined in class "Base" (reportIncompatibleMethodOverride)
overloads_invalid.py:173:9 - error: Method "final_method" overrides class "Base" in an incompatible manner
overloads_invalid.py:176:9 - error: Method "final_method" cannot override final method defined in class "Base" (reportIncompatibleMethodOverride)
overloads_invalid.py:176:9 - error: Method "final_method" overrides class "Base" in an incompatible manner
  Return type mismatch: base method returns type "int", override returns type "int | str"
    Type "int | str" is not assignable to type "int"
      "str" is not assignable to "int" (reportIncompatibleMethodOverride)
overloads_invalid.py:189:9 - error: Method "bad_override" is marked as override, but no base method of same name is present (reportGeneralTypeIssues)
overloads_invalid.py:192:9 - error: Method "bad_override" is marked as override, but no base method of same name is present (reportGeneralTypeIssues)
"""
2 changes: 1 addition & 1 deletion conformance/results/pyright/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyright 1.1.391"
test_duration = 1.5
test_duration = 1.6
74 changes: 63 additions & 11 deletions conformance/results/pytype/overloads_invalid.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ Does not reject a function with a single @overload signature.
Does not reject a function with @overload signature but no implementation.
Does not allow an overload with no implementation in a Protocol or an abstract base class.
Does not error on overloads inconsistently decorated with `@staticmethod` or `@classmethod`.
Does not enforce any rules on location of @final decorator.
Does not enforce any rules on location of @final or @override decorators.
"""
conformance_automated = "Fail"
errors_diff = """
Line 217: Expected 1 errors
Lines 14, 15: Expected error (tag 'func1')
Lines 26, 27: Expected error (tag 'func2')
Lines 63, 64: Expected error (tag 'not_abstract')
Expand All @@ -25,9 +26,11 @@ Line 129: Unexpected errors ['overloads_invalid.py:129:9: \\x1b[1m\\x1b[31merror
Line 143: Unexpected errors ['overloads_invalid.py:143:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in invalid_final: bad return type [bad-return-type]', 'overloads_invalid.py:143:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in invalid_final: bad return type [bad-return-type]']
Line 160: Unexpected errors ['overloads_invalid.py:160:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in invalid_final_2: bad return type [bad-return-type]', 'overloads_invalid.py:160:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in invalid_final_2: bad return type [bad-return-type]']
Line 165: Unexpected errors ['overloads_invalid.py:165:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in good_override: bad return type [bad-return-type]']
Line 174: Unexpected errors ['overloads_invalid.py:174:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in final_method: bad return type [bad-return-type]']
Line 190: Unexpected errors ['overloads_invalid.py:190:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in bad_override: bad return type [bad-return-type]', 'overloads_invalid.py:190:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in bad_override: bad return type [bad-return-type]']
Line 209: Unexpected errors ['overloads_invalid.py:209:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in good_override: bad return type [bad-return-type]', 'overloads_invalid.py:209:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in good_override: bad return type [bad-return-type]']
Line 168: Unexpected errors ['overloads_invalid.py:168:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in to_override: bad return type [bad-return-type]']
Line 177: Unexpected errors ['overloads_invalid.py:177:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in final_method: bad return type [bad-return-type]']
Line 193: Unexpected errors ['overloads_invalid.py:193:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in bad_override: bad return type [bad-return-type]', 'overloads_invalid.py:193:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in bad_override: bad return type [bad-return-type]']
Line 212: Unexpected errors ['overloads_invalid.py:212:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in good_override: bad return type [bad-return-type]', 'overloads_invalid.py:212:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in good_override: bad return type [bad-return-type]']
Line 229: Unexpected errors ['overloads_invalid.py:229:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in to_override: bad return type [bad-return-type]', 'overloads_invalid.py:229:9: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in to_override: bad return type [bad-return-type]']
"""
output = """
overloads_invalid.py:6:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: typing.override not supported yet [not-supported-yet]
Expand Down Expand Up @@ -105,7 +108,12 @@ overloads_invalid.py:165:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in good
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:168:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Child overrides final method final_method, defined in base class Base [final-error]
overloads_invalid.py:168:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in to_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:171:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Class Child overrides final method final_method, defined in base class Base [final-error]
class Child(Base): # E[override-final]
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
Expand Down Expand Up @@ -192,34 +200,78 @@ class Child(Base): # E[override-final]
...
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
overloads_invalid.py:174:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in final_method: bad return type [bad-return-type]
\u001b[1m\u001b[31m\u001b[39m\u001b[0m
# This is the wrong way to use @override with an overloaded method, and
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
# should emit an error:
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
\u001b[1m\u001b[31m\u001b[39m\u001b[0m
@overload # E: @override should appear only on implementation
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
@override
\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m
def to_override(self, x: int) -> int:
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
...
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
\u001b[1m\u001b[31m\u001b[39m\u001b[0m
@overload
\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m
@override
\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m
def to_override(self, x: str) -> str:
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
...
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
\u001b[1m\u001b[31m\u001b[39m\u001b[0m
@override
\u001b[1m\u001b[31m~~~~~~~~~~~~~\u001b[39m\u001b[0m
def to_override(self, x: int | str) -> int | str:
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
...
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
overloads_invalid.py:177:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in final_method: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:181:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in Child: Attribute 'bad_override' not found on any parent class [override-error]
overloads_invalid.py:184:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in Child: Attribute 'bad_override' not found on any parent class [override-error]
def bad_override(self, x: int) -> int: # E[bad_override]
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
...
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m
overloads_invalid.py:190:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in bad_override: bad return type [bad-return-type]
overloads_invalid.py:193:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in bad_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:193:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in bad_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:212:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in good_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:190:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in bad_override: bad return type [bad-return-type]
overloads_invalid.py:212:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in good_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:209:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in good_override: bad return type [bad-return-type]
overloads_invalid.py:229:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in to_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
overloads_invalid.py:209:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in good_override: bad return type [bad-return-type]
overloads_invalid.py:229:9: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in to_override: bad return type [bad-return-type]
...
\u001b[1m\u001b[31m~~~\u001b[39m\u001b[0m
Expand Down
2 changes: 1 addition & 1 deletion conformance/results/pytype/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pytype 2024.10.11"
test_duration = 30.6
test_duration = 30.7
Loading

0 comments on commit 60f9f81

Please sign in to comment.