Skip to content

Commit 57bc518

Browse files
committed
Make overloaded constructors consistent in error messages
1 parent 30b2a2d commit 57bc518

10 files changed

Lines changed: 55 additions & 50 deletions

mypy/messages.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,30 +3028,35 @@ def [T <: int] f(self, x: int, y: T) -> None
30283028
s += ", /"
30293029
slash = True
30303030

3031-
# If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list
30323031
definition = get_func_def(tp)
3032+
3033+
# Extract function name, prefer the "human-readable" name if available.
3034+
func_name = None
3035+
if tp.name:
3036+
func_name = tp.name.split()[0] # skip "of Class" part
3037+
elif isinstance(definition, FuncDef):
3038+
func_name = definition.name
3039+
3040+
# If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list
3041+
first_arg = None
30333042
if (
30343043
isinstance(definition, FuncDef)
30353044
and hasattr(definition, "arguments")
30363045
and not tp.from_concatenate
30373046
):
30383047
definition_arg_names = [arg.variable.name for arg in definition.arguments]
3039-
if (
3040-
len(definition_arg_names) > len(tp.arg_names)
3041-
and definition_arg_names[0]
3042-
and not skip_self
3043-
):
3044-
if s:
3045-
s = ", " + s
3046-
s = definition_arg_names[0] + s
3047-
s = f"{definition.name}({s})"
3048-
elif tp.name:
3048+
if len(definition_arg_names) > len(tp.arg_names) and definition_arg_names[0]:
3049+
first_arg = definition_arg_names[0]
3050+
else:
3051+
# TODO: avoid different logic for incremental runs.
30493052
first_arg = get_first_arg(tp)
3050-
if first_arg:
3051-
if s:
3052-
s = ", " + s
3053-
s = first_arg + s
3054-
s = f"{tp.name.split()[0]}({s})" # skip "of Class" part
3053+
3054+
if first_arg and not skip_self:
3055+
if s:
3056+
s = ", " + s
3057+
s = first_arg + s
3058+
if func_name:
3059+
s = f"{func_name}({s})"
30553060
else:
30563061
s = f"({s})"
30573062

test-data/unit/check-classes.test

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3492,8 +3492,8 @@ c.a # E: "C" has no attribute "a"
34923492
C('', '')
34933493
C('') # E: No overload variant of "C" matches argument type "str" \
34943494
# N: Possible overload variants: \
3495-
# N: def __new__(cls, foo: int) -> C \
3496-
# N: def __new__(cls, x: str, y: str) -> C
3495+
# N: def C(cls, foo: int) -> C \
3496+
# N: def C(cls, x: str, y: str) -> C
34973497
[builtins fixtures/__new__.pyi]
34983498

34993499

@@ -3922,8 +3922,8 @@ u = new(User)
39223922
[out]
39233923
tmp/foo.pyi:17: error: No overload variant of "User" matches argument type "str"
39243924
tmp/foo.pyi:17: note: Possible overload variants:
3925-
tmp/foo.pyi:17: note: def __init__(self) -> U
3926-
tmp/foo.pyi:17: note: def __init__(self, arg: int) -> U
3925+
tmp/foo.pyi:17: note: def User(self) -> U
3926+
tmp/foo.pyi:17: note: def User(self, arg: int) -> U
39273927
tmp/foo.pyi:18: error: Too many arguments for "foo" of "User"
39283928

39293929
[case testTypeUsingTypeCInUpperBound]
@@ -8498,7 +8498,7 @@ def identity_wrapper(func: FuncT) -> FuncT:
84988498
def foo(self: Any) -> str:
84998499
return ""
85008500

8501-
[case testParentClassWithTypeAliasAndSubclassWithMethod_no_parallel]
8501+
[case testParentClassWithTypeAliasAndSubclassWithMethod]
85028502
from typing import Any, Callable, TypeVar
85038503

85048504
class Parent:
@@ -8517,7 +8517,7 @@ class Child(Parent):
85178517
return val
85188518
def bar(self, val: str) -> str: # E: Signature of "bar" incompatible with supertype "Parent" \
85198519
# N: Superclass: \
8520-
# N: def __init__(self) -> bar \
8520+
# N: def bar(self) -> bar \
85218521
# N: Subclass: \
85228522
# N: def bar(self, val: str) -> str
85238523
return val

test-data/unit/check-flags.test

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,19 +2477,19 @@ cb(lambda x: a) # OK
24772477
fn = lambda x: a
24782478
cb(fn)
24792479

2480-
[case testShowErrorCodeLinks_no_parallel]
2480+
[case testShowErrorCodeLinks]
24812481
# flags: --show-error-codes --show-error-code-links
24822482

24832483
x: int = "" # E: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment]
24842484
list(1) # E: No overload variant of "list" matches argument type "int" [call-overload] \
24852485
# N: Possible overload variants: \
2486-
# N: def [T] __init__(self) -> list[T] \
2487-
# N: def [T] __init__(self, x: Iterable[T]) -> list[T] \
2486+
# N: def [T] list(self) -> list[T] \
2487+
# N: def [T] list(self, x: Iterable[T]) -> list[T] \
24882488
# N: See https://mypy.rtfd.io/en/stable/_refs.html#code-call-overload for more info
24892489
list(2) # E: No overload variant of "list" matches argument type "int" [call-overload] \
24902490
# N: Possible overload variants: \
2491-
# N: def [T] __init__(self) -> list[T] \
2492-
# N: def [T] __init__(self, x: Iterable[T]) -> list[T]
2491+
# N: def [T] list(self) -> list[T] \
2492+
# N: def [T] list(self, x: Iterable[T]) -> list[T]
24932493
[builtins fixtures/list.pyi]
24942494

24952495
[case testNestedGenericInAliasDisallow]

test-data/unit/check-inference.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,13 +1748,13 @@ def f(blocks: Any): # E: Name "Any" is not defined \
17481748
to_process = list(blocks)
17491749
[builtins fixtures/list.pyi]
17501750

1751-
[case testSpecialCaseEmptyListInitialization2_no_parallel]
1751+
[case testSpecialCaseEmptyListInitialization2]
17521752
def f(blocks: object):
17531753
to_process = []
17541754
to_process = list(blocks) # E: No overload variant of "list" matches argument type "object" \
17551755
# N: Possible overload variants: \
1756-
# N: def [T] __init__(self) -> list[T] \
1757-
# N: def [T] __init__(self, x: Iterable[T]) -> list[T]
1756+
# N: def [T] list(self) -> list[T] \
1757+
# N: def [T] list(self, x: Iterable[T]) -> list[T]
17581758
[builtins fixtures/list.pyi]
17591759

17601760
[case testInferListInitializedToEmptyAndAssigned]

test-data/unit/check-overloading.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -625,8 +625,8 @@ a = A(a)
625625
a = A(b)
626626
a = A(object()) # E: No overload variant of "A" matches argument type "object" \
627627
# N: Possible overload variants: \
628-
# N: def __init__(self, a: A) -> A \
629-
# N: def __init__(self, b: B) -> A
628+
# N: def A(self, a: A) -> A \
629+
# N: def A(self, b: B) -> A
630630

631631
class A:
632632
@overload

test-data/unit/check-protocols.test

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,7 +3609,7 @@ test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P"
36093609
# N: Expected: \
36103610
# N: def __call__(x: int, y: int) -> Any \
36113611
# N: Got: \
3612-
# N: def __init__(x: int, y: str) -> C \
3612+
# N: def C(x: int, y: str) -> C \
36133613
# N: "P.__call__" has type "def __call__(self, x: int, y: int) -> Any"
36143614

36153615
[case testProtocolClassObjectPureCallback]
@@ -3631,7 +3631,7 @@ test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P"
36313631
# N: Expected: \
36323632
# N: def __call__(x: int, y: int) -> Any \
36333633
# N: Got: \
3634-
# N: def __init__(x: int, y: str) -> C \
3634+
# N: def C(x: int, y: str) -> C \
36353635
# N: "P.__call__" has type "def __call__(self, x: int, y: int) -> Any"
36363636
[builtins fixtures/type.pyi]
36373637

@@ -3654,7 +3654,7 @@ p: P = C # E: Incompatible types in assignment (expression has type "type[C]",
36543654
# N: Expected: \
36553655
# N: def __call__(app: int) -> Callable[[str], None] \
36563656
# N: Got: \
3657-
# N: def __init__(app: str) -> C \
3657+
# N: def C(app: str) -> C \
36583658
# N: "P.__call__" has type "def __call__(self, app: int) -> Callable[[str], None]"
36593659

36603660
[builtins fixtures/type.pyi]
@@ -3890,7 +3890,7 @@ other_flag = False
38903890
def update() -> str: ...
38913891
[builtins fixtures/module.pyi]
38923892

3893-
[case testModuleAsProtocolImplementationClassObject_no_parallel]
3893+
[case testModuleAsProtocolImplementationClassObject]
38943894
import runner
38953895
import bad_runner
38963896
from typing import Callable, Protocol
@@ -3909,7 +3909,7 @@ run(bad_runner) # E: Argument 1 to "run" has incompatible type Module; expected
39093909
# N: Expected: \
39103910
# N: def (int, /) -> Result \
39113911
# N: Got: \
3912-
# N: def __init__(arg: str) -> Run
3912+
# N: def Run(arg: str) -> Run
39133913

39143914
[file runner.py]
39153915
class Run:
@@ -3922,7 +3922,7 @@ class Run:
39223922
def __init__(self, arg: str) -> None: ...
39233923
[builtins fixtures/module.pyi]
39243924

3925-
[case testModuleAsProtocolImplementationTypeAlias_no_parallel]
3925+
[case testModuleAsProtocolImplementationTypeAlias]
39263926
import runner
39273927
import bad_runner
39283928
from typing import Callable, Protocol
@@ -3941,7 +3941,7 @@ run(bad_runner) # E: Argument 1 to "run" has incompatible type Module; expected
39413941
# N: Expected: \
39423942
# N: def (int, /) -> Result \
39433943
# N: Got: \
3944-
# N: def __init__(arg: str) -> Run
3944+
# N: def Run(arg: str) -> Run
39453945

39463946
[file runner.py]
39473947
class Run:

test-data/unit/check-python311.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ myclass2 = MyClass(float, float)
137137
reveal_type(myclass2) # N: Revealed type is "__main__.MyClass[builtins.float, builtins.float]"
138138
myclass3 = MyClass(float, float, float) # E: No overload variant of "MyClass" matches argument types "type[float]", "type[float]", "type[float]" \
139139
# N: Possible overload variants: \
140-
# N: def [T1, T2] __init__(self) -> MyClass[None, None] \
141-
# N: def [T1, T2] __init__(self, type[T1], /) -> MyClass[T1, None] \
142-
# N: def [T1, T2] __init__(type[T1], type[T2], /) -> MyClass[T1, T2]
140+
# N: def [T1, T2] MyClass(self) -> MyClass[None, None] \
141+
# N: def [T1, T2] MyClass(self, type[T1], /) -> MyClass[T1, None] \
142+
# N: def [T1, T2] MyClass(type[T1], type[T2], /) -> MyClass[T1, T2]
143143
reveal_type(myclass3) # N: Revealed type is "Any"
144144
[builtins fixtures/tuple.pyi]
145145

test-data/unit/check-selftype.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ def bad(x: str) -> str: ...
749749
reveal_type(ci.from_item(conv)) # N: Revealed type is "builtins.str"
750750
ci.from_item(bad) # E: Argument 1 to "from_item" of "C" has incompatible type "Callable[[str], str]"; expected "Callable[[int], str]"
751751

752-
[case testSelfTypeRestrictedMethodOverloadInit_no_parallel]
752+
[case testSelfTypeRestrictedMethodOverloadInit]
753753
from typing import TypeVar
754754
from lib import P, C
755755

@@ -767,8 +767,8 @@ class SubP(P[T]):
767767

768768
SubP('no') # E: No overload variant of "SubP" matches argument type "str" \
769769
# N: Possible overload variants: \
770-
# N: def [T] __init__(self, use_str: Literal[True]) -> SubP[T] \
771-
# N: def [T] __init__(self, use_str: Literal[False]) -> SubP[T]
770+
# N: def [T] SubP(self, use_str: Literal[True]) -> SubP[T] \
771+
# N: def [T] SubP(self, use_str: Literal[False]) -> SubP[T]
772772

773773
# This is a bit unfortunate: we don't have a way to map the overloaded __init__ to subtype.
774774
x = SubP(use_str=True) # E: Need type annotation for "x"

test-data/unit/check-type-aliases.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,16 +1339,16 @@ a: A
13391339
reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]"
13401340
[builtins fixtures/tuple.pyi]
13411341

1342-
[case testTypeAliasDict_no_parallel]
1342+
[case testTypeAliasDict]
13431343
D = dict[str, int]
13441344
d = D()
13451345
reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
13461346
reveal_type(D()) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
13471347
reveal_type(D(x=1)) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
13481348
reveal_type(D(x="asdf")) # E: No overload variant of "dict" matches argument type "str" \
13491349
# N: Possible overload variants: \
1350-
# N: def __init__(self, **kwargs: int) -> dict[str, int] \
1351-
# N: def __init__(self, arg: Iterable[tuple[str, int]], **kwargs: int) -> dict[str, int] \
1350+
# N: def dict(self, **kwargs: int) -> dict[str, int] \
1351+
# N: def dict(self, arg: Iterable[tuple[str, int]], **kwargs: int) -> dict[str, int] \
13521352
# N: Revealed type is "Any"
13531353
[builtins fixtures/dict.pyi]
13541354

test-data/unit/fine-grained.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7381,8 +7381,8 @@ class C:
73817381
==
73827382
a.py:2: error: No overload variant of "B" matches argument type "int"
73837383
a.py:2: note: Possible overload variants:
7384-
a.py:2: note: def __init__(self, x: str) -> B
7385-
a.py:2: note: def __init__(self, x: str, y: int) -> B
7384+
a.py:2: note: def B(self, x: str) -> B
7385+
a.py:2: note: def B(self, x: str, y: int) -> B
73867386

73877387
[case testOverloadedToNormalMethodMetaclass]
73887388
import a

0 commit comments

Comments
 (0)