diff --git a/mypy/nodes.py b/mypy/nodes.py index 9cfc61c80b3e..e597fa3490ef 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -989,6 +989,8 @@ def serialize(self) -> JsonDict: ), "deprecated": self.deprecated, "original_first_arg": self.original_first_arg, + "line": self.line, + "column": self.column, } @classmethod @@ -1018,6 +1020,8 @@ def deserialize(cls, data: JsonDict) -> FuncDef: else None ) ret.deprecated = data["deprecated"] + ret.line = data["line"] + ret.column = data["column"] # Leave these uninitialized so that future uses will trigger an error del ret.arguments del ret.max_pos @@ -1040,6 +1044,8 @@ def write(self, data: Buffer) -> None: self.dataclass_transform_spec.write(data) write_str_opt(data, self.deprecated) write_str_opt(data, self.original_first_arg) + write_int(data, self.line) + write_int(data, self.column) @classmethod def read(cls, data: Buffer) -> FuncDef: @@ -1058,6 +1064,8 @@ def read(cls, data: Buffer) -> FuncDef: ret.dataclass_transform_spec = DataclassTransformSpec.read(data) ret.deprecated = read_str_opt(data) ret.original_first_arg = read_str_opt(data) + ret.line = read_int(data) + ret.column = read_int(data) # Leave these uninitialized so that future uses will trigger an error del ret.arguments del ret.max_pos diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 9f5c811dc0a1..a644a4c7153b 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -210,6 +210,7 @@ def foo() -> int: [out2] tmp/mod2.py:4: error: Incompatible return value type (got "str", expected "int") +-- Function line numbers can affect error messages, so should be part of public interface. [case testIncrementalInternalScramble] import mod1 @@ -236,8 +237,8 @@ def bar() -> int: def baz() -> int: return 42 -[rechecked mod2] -[stale] +[rechecked mod1, mod2] +[stale mod2] [case testIncrementalMethodInterfaceChange] import mod1 @@ -6916,6 +6917,23 @@ import does_not_exist [out] [out2] +[case testCachedUnexpectedKeywordArgument] +import a +[file a.py] +import b +b.lol(uhhhh=12) # tweak +[file a.py.2] +import b +b.lol(uhhhh=12) +[file b.py] +def lol() -> None: pass +[out] +tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" +tmp/b.py:1: note: "lol" defined here +[out2] +tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" +tmp/b.py:1: note: "lol" defined here + [case testIncrementalNoCrashOnParamSpecPrefixUpdateMethod] import impl [file impl.py] diff --git a/test-data/unit/check-serialize.test b/test-data/unit/check-serialize.test index 03c185a5694b..eda8f7a5d893 100644 --- a/test-data/unit/check-serialize.test +++ b/test-data/unit/check-serialize.test @@ -158,7 +158,7 @@ def f(__x: int) -> None: pass [out2] tmp/a.py:3: error: Argument 1 to "f" has incompatible type "str"; expected "int" tmp/a.py:4: error: Unexpected keyword argument "__x" for "f" -tmp/b.py: note: "f" defined here +tmp/b.py:1: note: "f" defined here [case testSerializeArgumentKindsErrors] import a @@ -224,7 +224,7 @@ def f(x: int) -> int: pass [out2] tmp/a.py:2: note: Revealed type is "builtins.str" tmp/a.py:3: error: Unexpected keyword argument "x" for "f" -tmp/b.py: note: "f" defined here +tmp/b.py:4: note: "f" defined here [case testSerializeTypeGuardFunction] import a diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 1bddee0e5ed2..3f3a2c638f38 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -5178,6 +5178,20 @@ def g(y: T) -> T: a.py:2: error: Unexpected keyword argument "x" c.py:4: note: Called function defined here +[case testFineGrainedUnexpectedKeywordArgument] +import a +[file a.py] +import b +[file a.py.2] +import b +b.lol(uhhhh=12) +[file b.py] +def lol() -> None: pass +[out] +== +a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" +b.py:1: note: "lol" defined here + [case testGenericFineCallableInBound] import a [file a.py]