diff --git a/mypy/checker.py b/mypy/checker.py index fe978385d12c..4cad81cd0ca6 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1262,6 +1262,19 @@ def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None: msg += f"tuple argument {name[12:]}" else: msg += f'argument "{name}"' + if ( + not self.options.implicit_optional + and isinstance(arg.initializer, NameExpr) + and arg.initializer.fullname == "builtins.None" + ): + notes = [ + "PEP 484 prohibits implicit Optional. " + "Accordingly, mypy has changed its default to no_implicit_optional=True", + "Use https://github.com/hauntsaninja/no_implicit_optional to automatically " + "upgrade your codebase", + ] + else: + notes = None self.check_simple_assignment( arg.variable.type, arg.initializer, @@ -1269,6 +1282,7 @@ def check_default_args(self, item: FuncItem, body_is_trivial: bool) -> None: msg=ErrorMessage(msg, code=codes.ASSIGNMENT), lvalue_name="argument", rvalue_name="default", + notes=notes, ) def is_forward_op_method(self, method_name: str) -> bool: @@ -3739,6 +3753,8 @@ def check_simple_assignment( msg: ErrorMessage = message_registry.INCOMPATIBLE_TYPES_IN_ASSIGNMENT, lvalue_name: str = "variable", rvalue_name: str = "expression", + *, + notes: list[str] | None = None, ) -> Type: if self.is_stub and isinstance(rvalue, EllipsisExpr): # '...' is always a valid initializer in a stub. @@ -3763,6 +3779,7 @@ def check_simple_assignment( msg, f"{rvalue_name} has type", f"{lvalue_name} has type", + notes=notes, ) return rvalue_type @@ -5666,6 +5683,7 @@ def check_subtype( subtype_label: str | None = None, supertype_label: str | None = None, *, + notes: list[str] | None = None, code: ErrorCode | None = None, outer_context: Context | None = None, ) -> bool: @@ -5681,6 +5699,7 @@ def check_subtype( subtype_label: str | None = None, supertype_label: str | None = None, *, + notes: list[str] | None = None, outer_context: Context | None = None, ) -> bool: ... @@ -5694,6 +5713,7 @@ def check_subtype( subtype_label: str | None = None, supertype_label: str | None = None, *, + notes: list[str] | None = None, code: ErrorCode | None = None, outer_context: Context | None = None, ) -> bool: @@ -5714,7 +5734,7 @@ def check_subtype( return False extra_info: list[str] = [] note_msg = "" - notes: list[str] = [] + notes = notes or [] if subtype_label is not None or supertype_label is not None: subtype_str, supertype_str = format_type_distinctly(orig_subtype, orig_supertype) if subtype_label is not None: @@ -5725,7 +5745,7 @@ def check_subtype( outer_context or context, subtype, supertype, supertype_str ) if isinstance(subtype, Instance) and isinstance(supertype, Instance): - notes = append_invariance_notes([], subtype, supertype) + notes = append_invariance_notes(notes, subtype, supertype) if extra_info: msg = msg.with_additional_msg(" (" + ", ".join(extra_info) + ")") diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index d40ebf993581..db07290f7b40 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -136,7 +136,9 @@ 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 argument "x" (default has type "None", argument has type "int") \ + # N: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True \ + # N: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase pass [out] @@ -151,7 +153,9 @@ 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 argument "x" (default has type "None", argument has type "int") \ + # N: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True \ + # N: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase # type: (int) -> None pass [out]