Skip to content

Commit e3827a1

Browse files
authored
checker: disallow specifying both ErrorMessage and code (#13535)
1 parent 1a3d601 commit e3827a1

File tree

4 files changed

+64
-38
lines changed

4 files changed

+64
-38
lines changed

mypy/checker.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,7 +1218,6 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str | None) ->
12181218
supertype=return_type,
12191219
context=defn,
12201220
msg=message_registry.INCOMPATIBLE_RETURN_VALUE_TYPE,
1221-
code=codes.RETURN_VALUE,
12221221
)
12231222

12241223
self.return_types.pop()
@@ -4008,7 +4007,6 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
40084007
context=s.expr,
40094008
outer_context=s,
40104009
msg=message_registry.INCOMPATIBLE_RETURN_VALUE_TYPE,
4011-
code=codes.RETURN_VALUE,
40124010
)
40134011
else:
40144012
# Empty returns are valid in Generators with Any typed returns, but not in
@@ -5581,6 +5579,34 @@ def refine_away_none_in_comparison(
55815579
#
55825580
# Helpers
55835581
#
5582+
@overload
5583+
def check_subtype(
5584+
self,
5585+
subtype: Type,
5586+
supertype: Type,
5587+
context: Context,
5588+
msg: str,
5589+
subtype_label: str | None = None,
5590+
supertype_label: str | None = None,
5591+
*,
5592+
code: ErrorCode | None = None,
5593+
outer_context: Context | None = None,
5594+
) -> bool:
5595+
...
5596+
5597+
@overload
5598+
def check_subtype(
5599+
self,
5600+
subtype: Type,
5601+
supertype: Type,
5602+
context: Context,
5603+
msg: ErrorMessage = message_registry.INCOMPATIBLE_TYPES,
5604+
subtype_label: str | None = None,
5605+
supertype_label: str | None = None,
5606+
*,
5607+
outer_context: Context | None = None,
5608+
) -> bool:
5609+
...
55845610

55855611
def check_subtype(
55865612
self,
@@ -5598,17 +5624,16 @@ def check_subtype(
55985624
if is_subtype(subtype, supertype, options=self.options):
55995625
return True
56005626

5601-
if isinstance(msg, ErrorMessage):
5602-
msg_text = msg.value
5603-
code = msg.code
5604-
else:
5605-
msg_text = msg
5627+
if isinstance(msg, str):
5628+
msg = ErrorMessage(msg, code=code)
5629+
del code
5630+
56065631
orig_subtype = subtype
56075632
subtype = get_proper_type(subtype)
56085633
orig_supertype = supertype
56095634
supertype = get_proper_type(supertype)
56105635
if self.msg.try_report_long_tuple_assignment_error(
5611-
subtype, supertype, context, msg_text, subtype_label, supertype_label, code=code
5636+
subtype, supertype, context, msg, subtype_label, supertype_label
56125637
):
56135638
return False
56145639
extra_info: list[str] = []
@@ -5626,29 +5651,29 @@ def check_subtype(
56265651
if isinstance(subtype, Instance) and isinstance(supertype, Instance):
56275652
notes = append_invariance_notes([], subtype, supertype)
56285653
if extra_info:
5629-
msg_text += " (" + ", ".join(extra_info) + ")"
5654+
msg = msg.with_additional_msg(" (" + ", ".join(extra_info) + ")")
56305655

5631-
self.fail(ErrorMessage(msg_text, code=code), context)
5656+
self.fail(msg, context)
56325657
for note in notes:
5633-
self.msg.note(note, context, code=code)
5658+
self.msg.note(note, context, code=msg.code)
56345659
if note_msg:
5635-
self.note(note_msg, context, code=code)
5636-
self.msg.maybe_note_concatenate_pos_args(subtype, supertype, context, code=code)
5660+
self.note(note_msg, context, code=msg.code)
5661+
self.msg.maybe_note_concatenate_pos_args(subtype, supertype, context, code=msg.code)
56375662
if (
56385663
isinstance(supertype, Instance)
56395664
and supertype.type.is_protocol
56405665
and isinstance(subtype, (Instance, TupleType, TypedDictType))
56415666
):
5642-
self.msg.report_protocol_problems(subtype, supertype, context, code=code)
5667+
self.msg.report_protocol_problems(subtype, supertype, context, code=msg.code)
56435668
if isinstance(supertype, CallableType) and isinstance(subtype, Instance):
56445669
call = find_member("__call__", subtype, subtype, is_operator=True)
56455670
if call:
5646-
self.msg.note_call(subtype, call, context, code=code)
5671+
self.msg.note_call(subtype, call, context, code=msg.code)
56475672
if isinstance(subtype, (CallableType, Overloaded)) and isinstance(supertype, Instance):
56485673
if supertype.type.is_protocol and supertype.type.protocol_members == ["__call__"]:
56495674
call = find_member("__call__", supertype, subtype, is_operator=True)
56505675
assert call is not None
5651-
self.msg.note_call(supertype, call, context, code=code)
5676+
self.msg.note_call(supertype, call, context, code=msg.code)
56525677
self.check_possible_missing_await(subtype, supertype, context)
56535678
return False
56545679

mypy/checkexpr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ def check_typeddict_call_with_kwargs(
819819
lvalue_type=item_expected_type,
820820
rvalue=item_value,
821821
context=item_value,
822-
msg=message_registry.INCOMPATIBLE_TYPES,
822+
msg=message_registry.INCOMPATIBLE_TYPES.value,
823823
lvalue_name=f'TypedDict item "{item_name}"',
824824
rvalue_name="expression",
825825
code=codes.TYPEDDICT_ITEM,

mypy/message_registry.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class ErrorMessage(NamedTuple):
2121
def format(self, *args: object, **kwargs: object) -> ErrorMessage:
2222
return ErrorMessage(self.value.format(*args, **kwargs), code=self.code)
2323

24+
def with_additional_msg(self, info: str) -> ErrorMessage:
25+
return ErrorMessage(self.value + info, code=self.code)
26+
2427

2528
# Invalid types
2629
INVALID_TYPE_RAW_ENUM_VALUE: Final = "Invalid type: try using Literal[{}.{}] instead?"
@@ -47,7 +50,7 @@ def format(self, *args: object, **kwargs: object) -> ErrorMessage:
4750
"supertypes"
4851
)
4952
YIELD_VALUE_EXPECTED: Final = ErrorMessage("Yield value expected")
50-
INCOMPATIBLE_TYPES: Final = "Incompatible types"
53+
INCOMPATIBLE_TYPES: Final = ErrorMessage("Incompatible types")
5154
INCOMPATIBLE_TYPES_IN_ASSIGNMENT: Final = "Incompatible types in assignment"
5255
INCOMPATIBLE_TYPES_IN_AWAIT: Final = ErrorMessage('Incompatible types in "await"')
5356
INCOMPATIBLE_REDEFINITION: Final = ErrorMessage("Incompatible redefinition")

mypy/messages.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,10 +2030,9 @@ def try_report_long_tuple_assignment_error(
20302030
subtype: ProperType,
20312031
supertype: ProperType,
20322032
context: Context,
2033-
msg: str = message_registry.INCOMPATIBLE_TYPES,
2033+
msg: message_registry.ErrorMessage,
20342034
subtype_label: str | None = None,
20352035
supertype_label: str | None = None,
2036-
code: ErrorCode | None = None,
20372036
) -> bool:
20382037
"""Try to generate meaningful error message for very long tuple assignment
20392038
@@ -2048,26 +2047,25 @@ def try_report_long_tuple_assignment_error(
20482047
):
20492048
lhs_type = supertype.args[0]
20502049
lhs_types = [lhs_type] * len(subtype.items)
2051-
self.generate_incompatible_tuple_error(
2052-
lhs_types, subtype.items, context, msg, code
2053-
)
2050+
self.generate_incompatible_tuple_error(lhs_types, subtype.items, context, msg)
20542051
return True
20552052
elif isinstance(supertype, TupleType) and (
20562053
len(subtype.items) > 10 or len(supertype.items) > 10
20572054
):
20582055
if len(subtype.items) != len(supertype.items):
20592056
if supertype_label is not None and subtype_label is not None:
2060-
error_msg = "{} ({} {}, {} {})".format(
2061-
msg,
2062-
subtype_label,
2063-
self.format_long_tuple_type(subtype),
2064-
supertype_label,
2065-
self.format_long_tuple_type(supertype),
2057+
msg = msg.with_additional_msg(
2058+
" ({} {}, {} {})".format(
2059+
subtype_label,
2060+
self.format_long_tuple_type(subtype),
2061+
supertype_label,
2062+
self.format_long_tuple_type(supertype),
2063+
)
20662064
)
2067-
self.fail(error_msg, context, code=code)
2065+
self.fail(msg.value, context, code=msg.code)
20682066
return True
20692067
self.generate_incompatible_tuple_error(
2070-
supertype.items, subtype.items, context, msg, code
2068+
supertype.items, subtype.items, context, msg
20712069
)
20722070
return True
20732071
return False
@@ -2087,8 +2085,7 @@ def generate_incompatible_tuple_error(
20872085
lhs_types: list[Type],
20882086
rhs_types: list[Type],
20892087
context: Context,
2090-
msg: str = message_registry.INCOMPATIBLE_TYPES,
2091-
code: ErrorCode | None = None,
2088+
msg: message_registry.ErrorMessage,
20922089
) -> None:
20932090
"""Generate error message for individual incompatible tuple pairs"""
20942091
error_cnt = 0
@@ -2103,14 +2100,15 @@ def generate_incompatible_tuple_error(
21032100
)
21042101
error_cnt += 1
21052102

2106-
error_msg = msg + f" ({str(error_cnt)} tuple items are incompatible"
2103+
info = f" ({str(error_cnt)} tuple items are incompatible"
21072104
if error_cnt - 3 > 0:
2108-
error_msg += f"; {str(error_cnt - 3)} items are omitted)"
2105+
info += f"; {str(error_cnt - 3)} items are omitted)"
21092106
else:
2110-
error_msg += ")"
2111-
self.fail(error_msg, context, code=code)
2107+
info += ")"
2108+
msg = msg.with_additional_msg(info)
2109+
self.fail(msg.value, context, code=msg.code)
21122110
for note in notes:
2113-
self.note(note, context, code=code)
2111+
self.note(note, context, code=msg.code)
21142112

21152113
def add_fixture_note(self, fullname: str, ctx: Context) -> None:
21162114
self.note(f'Maybe your test fixture does not define "{fullname}"?', ctx)

0 commit comments

Comments
 (0)