Skip to content

Commit

Permalink
Fix [override] error with no line number when argument node has no li…
Browse files Browse the repository at this point in the history
…ne number (python#18122)

Refs python#18115

When a parameter type in a method override is incompatible with the
parameter type in the supertype definition, mypy emits an error using
the `Argument` node as the context.

However, sometimes the the `Argument` node doesn't have a line number
set, causing the error message to have no associated line number. This
happens with the `__replace__` methods created in the dataclass plugin,
which have line numbers set on the `FuncDef` nodes, but no line numbers
set on the individual argument nodes.

This PR fixes the missing line number in the error by falling-back to
the FuncDef line number when a line number isn't set on the `Argument`
node.

(As an alternative fix, we could add line numbers to the `Argument`
nodes in the dataclass plugin, but that looks like a more complicated
change since multiple methods would be affected).
  • Loading branch information
brianschubert authored Nov 7, 2024
1 parent eedee20 commit 3b00002
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
7 changes: 4 additions & 3 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2367,10 +2367,11 @@ def erase_override(t: Type) -> Type:
else:
continue
if not is_subtype(original_arg_type, erase_override(override_arg_type)):
context: Context = node
if isinstance(node, FuncDef) and not node.is_property:
context: Context = node.arguments[i + len(override.bound_args)]
else:
context = node
arg_node = node.arguments[i + len(override.bound_args)]
if arg_node.line != -1:
context = arg_node
self.msg.argument_incompatible_with_supertype(
i + 1,
name,
Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -2523,3 +2523,18 @@ reveal_type(replaced_2) # N: Revealed type is "__main__.Gen[builtins.int]"
Gen(2).__replace__(x="not an int") # E: Argument "x" to "__replace__" of "Gen" has incompatible type "str"; expected "int"

[builtins fixtures/tuple.pyi]

[case testDunderReplaceCovariantOverride]
# flags: --python-version 3.13
from dataclasses import dataclass

@dataclass
class Base:
a: object

@dataclass
class Child(Base): # E: Argument 1 of "__replace__" is incompatible with supertype "Base"; supertype defines the argument type as "object" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
a: int
[builtins fixtures/tuple.pyi]

0 comments on commit 3b00002

Please sign in to comment.