Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/source/stubs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ For example:
"""Some docstring"""
pass

# Error: Incompatible default for argument "foo" (default has
# type "ellipsis", argument has type "list[str]")
# Error: Incompatible default for parameter "foo" (default has
# type "ellipsis", parameter has type "list[str]")
def not_ok(self, foo: list[str] = ...) -> None:
print(foo)
30 changes: 15 additions & 15 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ def check_func_def(
# Type check initialization expressions.
body_is_trivial = is_trivial_body(defn.body)
if not self.can_skip_diagnostics:
self.check_default_args(item, body_is_trivial)
self.check_default_params(item, body_is_trivial)

# Type check body in a new scope.
with self.binder.top_frame_context():
Expand Down Expand Up @@ -1710,22 +1710,22 @@ def check_unbound_return_typevar(self, typ: CallableType) -> None:
context=typ.ret_type,
)

def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None:
for arg in item.arguments:
if arg.initializer is None:
def check_default_params(self, item: FuncItem, body_is_trivial: bool) -> None:
for param in item.arguments:
if param.initializer is None:
continue
if body_is_trivial and isinstance(arg.initializer, EllipsisExpr):
if body_is_trivial and isinstance(param.initializer, EllipsisExpr):
continue
name = arg.variable.name
name = param.variable.name
msg = "Incompatible default for "
if name.startswith("__tuple_arg_"):
msg += f"tuple argument {name[12:]}"
if name.startswith("__tuple_param_"):
msg += f"tuple parameter {name[12:]}"
else:
msg += f'argument "{name}"'
msg += f'parameter "{name}"'
if (
not self.options.implicit_optional
and isinstance(arg.initializer, NameExpr)
and arg.initializer.fullname == "builtins.None"
and isinstance(param.initializer, NameExpr)
and param.initializer.fullname == "builtins.None"
):
notes = [
"PEP 484 prohibits implicit Optional. "
Expand All @@ -1736,11 +1736,11 @@ def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None:
else:
notes = None
self.check_simple_assignment(
arg.variable.type,
arg.initializer,
context=arg.initializer,
param.variable.type,
param.initializer,
context=param.initializer,
msg=ErrorMessage(msg, code=codes.ASSIGNMENT),
lvalue_name="argument",
lvalue_name="parameter",
rvalue_name="default",
notes=notes,
)
Expand Down
2 changes: 1 addition & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5478,7 +5478,7 @@ def visit_lambda_expr(self, e: LambdaExpr) -> Type:
"""Type check lambda expression."""
old_in_lambda = self.in_lambda_expr
self.in_lambda_expr = True
self.chk.check_default_args(e, body_is_trivial=False)
self.chk.check_default_params(e, body_is_trivial=False)
inferred_type, type_override = self.infer_lambda_type_using_context(e)
if not inferred_type:
self.chk.return_types.append(AnyType(TypeOfAny.special_form))
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-columns.test
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ if int():

[case testColumnIncompatibleDefault]
if int():
def f(x: int = '') -> None: # E:20: Incompatible default for argument "x" (default has type "str", argument has type "int")
def f(x: int = '') -> None: # E:20: Incompatible default for parameter "x" (default has type "str", parameter has type "int")
pass

[case testColumnMissingProtocolMember]
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-errorcodes.test
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def f() -> int:
[case testErrorCodeAssignment]
x: str = 0 # E: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment]

def f(x: str = 0) -> None: # E: Incompatible default for argument "x" (default has type "int", argument has type "str") [assignment]
def f(x: str = 0) -> None: # E: Incompatible default for parameter "x" (default has type "int", parameter has type "str") [assignment]
pass

class A:
Expand Down
22 changes: 11 additions & 11 deletions test-data/unit/check-functions.test
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ if int():

[builtins fixtures/tuple.pyi]

[case testDefaultArgumentExpressions]
[case testDefaultParameterExpressions]
import typing
class B: pass
class A: pass
Expand All @@ -524,52 +524,52 @@ def f(x: 'A' = A()) -> None:
a = x # type: A
[out]

[case testDefaultArgumentExpressions2]
[case testDefaultParameterExpressions2]
import typing
class B: pass
class A: pass

def f(x: 'A' = B()) -> None: # E: Incompatible default for argument "x" (default has type "B", argument has type "A")
def f(x: 'A' = B()) -> None: # E: Incompatible default for parameter "x" (default has type "B", parameter has type "A")
b = x # type: B # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = x # type: A
[case testDefaultArgumentExpressionsGeneric]
[case testDefaultParameterExpressionsGeneric]
from typing import TypeVar
T = TypeVar('T', bound='A')

class B: pass
class A: pass

def f(x: T = B()) -> None: # E: Incompatible default for argument "x" (default has type "B", argument has type "T")
def f(x: T = B()) -> None: # E: Incompatible default for parameter "x" (default has type "B", parameter has type "T")
b = x # type: B # E: Incompatible types in assignment (expression has type "T", variable has type "B")
a = x # type: A
[case testDefaultArgumentsWithSubtypes]
[case testDefaultParametersWithSubtypes]
import typing
class A: pass
class B(A): pass

def f(x: 'B' = A()) -> None: # E: Incompatible default for argument "x" (default has type "A", argument has type "B")
def f(x: 'B' = A()) -> None: # E: Incompatible default for parameter "x" (default has type "A", parameter has type "B")
pass
def g(x: 'A' = B()) -> None:
pass
[out]

[case testMultipleDefaultArgumentExpressions]
[case testMultipleDefaultParameterExpressions]
import typing
class A: pass
class B: pass

def f(x: 'A' = B(), y: 'B' = B()) -> None: # E: Incompatible default for argument "x" (default has type "B", argument has type "A")
def f(x: 'A' = B(), y: 'B' = B()) -> None: # E: Incompatible default for parameter "x" (default has type "B", parameter has type "A")
pass
def h(x: 'A' = A(), y: 'B' = B()) -> None:
pass
[out]

[case testMultipleDefaultArgumentExpressions2]
[case testMultipleDefaultParameterExpressions2]
import typing
class A: pass
class B: pass

def g(x: 'A' = A(), y: 'B' = A()) -> None: # E: Incompatible default for argument "y" (default has type "A", argument has type "B")
def g(x: 'A' = A(), y: 'B' = A()) -> None: # E: Incompatible default for parameter "y" (default has type "A", parameter has type "B")
pass
[out]

Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-inference.test
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ from typing import Callable
def f(a: Callable[..., None] = lambda *a, **k: None):
pass

def g(a: Callable[..., None] = lambda *a, **k: 1): # E: Incompatible default for argument "a" (default has type "def (*a: Any, **k: Any) -> int", argument has type "Callable[..., None]")
def g(a: Callable[..., None] = lambda *a, **k: 1): # E: Incompatible default for parameter "a" (default has type "def (*a: Any, **k: Any) -> int", parameter has type "Callable[..., None]")
pass
[builtins fixtures/dict.pyi]

Expand Down
26 changes: 13 additions & 13 deletions test-data/unit/check-modules.test
Original file line number Diff line number Diff line change
Expand Up @@ -495,19 +495,19 @@ m.f('') # E: Argument 1 to "f" has incompatible type "str"; expected "int"
[file m.pyi]
def f(x: int = ...) -> None: pass

[case testEllipsisDefaultArgValueInStub2]
[case testEllipsisDefaultParamValueInStub2]
import m
def f1(x: int = ...) -> int: return 1
def f2(x: int = '') -> int: return 1
[file m.pyi]
def g1(x: int = ...) -> int: pass
def g2(x: int = '') -> int: pass
[out]
tmp/m.pyi:2: error: Incompatible default for argument "x" (default has type "str", argument has type "int")
main:2: error: Incompatible default for argument "x" (default has type "ellipsis", argument has type "int")
main:3: error: Incompatible default for argument "x" (default has type "str", argument has type "int")
tmp/m.pyi:2: error: Incompatible default for parameter "x" (default has type "str", parameter has type "int")
main:2: error: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "int")
main:3: error: Incompatible default for parameter "x" (default has type "str", parameter has type "int")

[case testEllipsisDefaultArgValueInNonStub]
[case testEllipsisDefaultParamValueInNonStub]
def ok_1(x: int = ...) -> None: pass
def ok_2(x: int = ...) -> None: ...
def ok_3(x: int = ...) -> None: raise NotImplementedError
Expand All @@ -516,16 +516,16 @@ def ok_5(x: int = ...) -> None:
"""Docstring here"""
pass

def bad_1(x: int = ...) -> None: 1 # E: Incompatible default for argument "x" (default has type "ellipsis", argument has type "int")
def bad_2(x: int = ...) -> None: # E: Incompatible default for argument "x" (default has type "ellipsis", argument has type "int")
def bad_1(x: int = ...) -> None: 1 # E: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "int")
def bad_2(x: int = ...) -> None: # E: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "int")
"""Docstring here"""
ok_1()
def bad_3(x: int = ...) -> None: # E: Incompatible default for argument "x" (default has type "ellipsis", argument has type "int")
def bad_3(x: int = ...) -> None: # E: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "int")
raise Exception("Some other exception")
[builtins fixtures/exception.pyi]
[out]

[case testEllipsisDefaultArgValueInNonStubsOverload]
[case testEllipsisDefaultParamValueInNonStubsOverload]
from typing import overload, Union

Both = Union[int, str]
Expand All @@ -534,7 +534,7 @@ Both = Union[int, str]
def foo(x: int, y: int = ...) -> int: ...
@overload
def foo(x: str, y: str = ...) -> str: ...
def foo(x: Both, y: Both = ...) -> Both: # E: Incompatible default for argument "y" (default has type "ellipsis", argument has type "int | str")
def foo(x: Both, y: Both = ...) -> Both: # E: Incompatible default for parameter "y" (default has type "ellipsis", parameter has type "int | str")
return x

@overload
Expand All @@ -546,7 +546,7 @@ def bar(x: Both, y: Both = ...) -> Both:
[builtins fixtures/exception.pyi]
[out]

[case testEllipsisDefaultArgValueInNonStubsMethods]
[case testEllipsisDefaultParamValueInNonStubsMethods]
from typing import Generic, Protocol, TypeVar
from abc import abstractmethod

Expand All @@ -555,14 +555,14 @@ class Wrap(Generic[T]): ...

class MyProtocol(Protocol):
def no_impl(self, x: Wrap[int] = ...) -> int: ...
def default_impl(self, x: Wrap[int] = ...) -> int: return 3 # E: Incompatible default for argument "x" (default has type "ellipsis", argument has type "Wrap[int]")
def default_impl(self, x: Wrap[int] = ...) -> int: return 3 # E: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "Wrap[int]")

class MyAbstractClass:
@abstractmethod
def no_impl(self, x: Wrap[int] = ...) -> int: raise NotImplementedError

@abstractmethod
def default_impl(self, x: Wrap[int] = ...) -> int: return 3 # E: Incompatible default for argument "x" (default has type "ellipsis", argument has type "Wrap[int]")
def default_impl(self, x: Wrap[int] = ...) -> int: return 3 # E: Incompatible default for parameter "x" (default has type "ellipsis", parameter has type "Wrap[int]")
[builtins fixtures/exception.pyi]
[out]

Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-optional.test
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ f(None)

[case testNoInferOptionalFromDefaultNone]
# flags: --no-implicit-optional
def f(x: int = None) -> None: # E: Incompatible default for argument "x" (default has type "None", argument has type "int") \
def f(x: int = None) -> None: # E: Incompatible default for parameter "x" (default has type "None", parameter has type "int") \
# N: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True \
# N: Use http://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
pass
Expand All @@ -153,7 +153,7 @@ f(None)

[case testNoInferOptionalFromDefaultNoneComment]
# flags: --no-implicit-optional
def f(x=None): # E: Incompatible default for argument "x" (default has type "None", argument has type "int") \
def f(x=None): # E: Incompatible default for parameter "x" (default has type "None", parameter has type "int") \
# N: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True \
# N: Use http://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
# type: (int) -> None
Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-python312.test
Original file line number Diff line number Diff line change
Expand Up @@ -1138,13 +1138,13 @@ class C[T]:
x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
return a

[case testPEP695ArgumentDefault]
[case testPEP695ParameterDefault]
from typing import cast

def f[T](
x: T =
T # E: Name "T" is not defined \
# E: Incompatible default for argument "x" (default has type "TypeVar", argument has type "T")
# E: Incompatible default for parameter "x" (default has type "TypeVar", parameter has type "T")
) -> T:
return x

Expand Down
32 changes: 16 additions & 16 deletions test-data/unit/check-python38.test
Original file line number Diff line number Diff line change
Expand Up @@ -114,35 +114,35 @@ def g(x: int): ...
0 # type: ignore
) # type: ignore # E: Unused "type: ignore" comment

[case testPEP570ArgTypesMissing]
[case testPEP570ParamTypesMissing]
# flags: --disallow-untyped-defs
def f(arg, /) -> None: ... # E: Function is missing a type annotation for one or more parameters
def f(x, /) -> None: ... # E: Function is missing a type annotation for one or more parameters

[case testPEP570ArgTypesBadDefault]
def f(arg: int = "ERROR", /) -> None: ... # E: Incompatible default for argument "arg" (default has type "str", argument has type "int")
[case testPEP570ParamTypesBadDefault]
def f(x: int = "ERROR", /) -> None: ... # E: Incompatible default for parameter "x" (default has type "str", parameter has type "int")

[case testPEP570ArgTypesDefault]
def f(arg: int = 0, /) -> None:
reveal_type(arg) # N: Revealed type is "builtins.int"
[case testPEP570ParamTypesDefault]
def f(x: int = 0, /) -> None:
reveal_type(x) # N: Revealed type is "builtins.int"

[case testPEP570ArgTypesRequired]
def f(arg: int, /) -> None:
reveal_type(arg) # N: Revealed type is "builtins.int"
[case testPEP570ParamTypesRequired]
def f(x: int, /) -> None:
reveal_type(x) # N: Revealed type is "builtins.int"

[case testPEP570Required]
def f(arg: int, /) -> None: ...
def f(x: int, /) -> None: ...
f(1)
f("ERROR") # E: Argument 1 to "f" has incompatible type "str"; expected "int"
f(arg=1) # E: Unexpected keyword argument "arg" for "f"
f(arg="ERROR") # E: Unexpected keyword argument "arg" for "f"
f(x=1) # E: Unexpected keyword argument "x" for "f"
f(x="ERROR") # E: Unexpected keyword argument "x" for "f"

[case testPEP570Default]
def f(arg: int = 0, /) -> None: ...
def f(x: int = 0, /) -> None: ...
f()
f(1)
f("ERROR") # E: Argument 1 to "f" has incompatible type "str"; expected "int"
f(arg=1) # E: Unexpected keyword argument "arg" for "f"
f(arg="ERROR") # E: Unexpected keyword argument "arg" for "f"
f(x=1) # E: Unexpected keyword argument "x" for "f"
f(x="ERROR") # E: Unexpected keyword argument "x" for "f"

[case testPEP570Calls]
# flags: --no-strict-optional
Expand Down