From 346e82b572f1a60effa28c506e80722a50d8e3fe Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 9 May 2025 09:58:18 -0400 Subject: [PATCH] ty_python_semantic: add union type context to function call type errors This context gets added only when calling a function through a union type. --- crates/ruff_benchmark/benches/ty.rs | 17 ++- .../resources/mdtest/annotations/new_types.md | 2 +- .../resources/mdtest/call/annotation.md | 4 +- .../mdtest/call/callable_instance.md | 4 +- .../resources/mdtest/call/constructor.md | 8 +- .../resources/mdtest/call/function.md | 16 +-- .../resources/mdtest/call/getattr_static.md | 2 +- .../resources/mdtest/call/invalid_syntax.md | 4 +- .../resources/mdtest/call/methods.md | 2 +- .../resources/mdtest/call/subclass_of.md | 2 +- .../resources/mdtest/call/union.md | 2 +- .../resources/mdtest/decorators.md | 2 +- .../mdtest/diagnostics/union_call.md | 4 +- .../doc/public_type_undeclared_symbols.md | 2 +- .../mdtest/generics/legacy/classes.md | 6 +- .../mdtest/generics/pep695/classes.md | 6 +- .../resources/mdtest/generics/scoping.md | 2 +- .../resources/mdtest/properties.md | 4 +- ...cy_syntax_-_Inferring_a_bound_typevar.snap | 2 +- ...tax_-_Inferring_a_constrained_typevar.snap | 2 +- ...95_syntax_-_Inferring_a_bound_typevar.snap | 2 +- ...tax_-_Inferring_a_constrained_typevar.snap | 2 +- ...lid_argument_type_diagnostics_-_Basic.snap | 2 +- ...t_type_diagnostics_-_Calls_to_methods.snap | 2 +- ...nt_type_diagnostics_-_Different_files.snap | 2 +- ..._diagnostics_-_Different_source_order.snap | 2 +- ...nt_type_diagnostics_-_Many_parameters.snap | 2 +- ...Many_parameters_across_multiple_lines.snap | 2 +- ...eters_with_multiple_invalid_arguments.snap | 6 +- ...hose_type_is_vendored_from_`typeshed`.snap | 2 +- ...gument_types_-_Keyword_only_arguments.snap | 2 +- ..._of_argument_types_-_Mix_of_arguments.snap | 2 +- ...argument_types_-_One_keyword_argument.snap | 2 +- ...y_of_argument_types_-_Only_positional.snap | 2 +- ..._argument_types_-_Synthetic_arguments.snap | 2 +- ...f_argument_types_-_Variadic_arguments.snap | 2 +- ...nt_types_-_Variadic_keyword_arguments.snap | 2 +- ...ction_types_-_A_smaller_scale_example.snap | 12 +- ...iple_variants_but_only_one_is_invalid.snap | 6 +- ...over_keyword_argument_related_reasons.snap | 12 +- ...s_-_Cover_non-keyword_related_reasons.snap | 46 ++++--- .../ty_python_semantic/src/types/call/bind.rs | 129 ++++++++++++++++-- 42 files changed, 235 insertions(+), 101 deletions(-) diff --git a/crates/ruff_benchmark/benches/ty.rs b/crates/ruff_benchmark/benches/ty.rs index c67a457d64..7a0fbbf8a1 100644 --- a/crates/ruff_benchmark/benches/ty.rs +++ b/crates/ruff_benchmark/benches/ty.rs @@ -59,26 +59,37 @@ type KeyDiagnosticFields = ( Severity, ); +// left: [ +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(8224..8254), "Argument to function `skip_until` is incorrect", Error), +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(16914..16948), "Argument to function `skip_until` is incorrect", Error), +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(17319..17363), "Argument to function `skip_until` is incorrect", Error), +// ] +//right: [ +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(8224..8254), "Argument to this function is incorrect", Error), +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(16914..16948), "Argument to this function is incorrect", Error), +// (Lint(LintName("invalid-argument-type")), Some("/src/tomllib/_parser.py"), Some(17319..17363), "Argument to this function is incorrect", Error), +// ] + static EXPECTED_TOMLLIB_DIAGNOSTICS: &[KeyDiagnosticFields] = &[ ( DiagnosticId::lint("invalid-argument-type"), Some("/src/tomllib/_parser.py"), Some(8224..8254), - "Argument to this function is incorrect", + "Argument to function `skip_until` is incorrect", Severity::Error, ), ( DiagnosticId::lint("invalid-argument-type"), Some("/src/tomllib/_parser.py"), Some(16914..16948), - "Argument to this function is incorrect", + "Argument to function `skip_until` is incorrect", Severity::Error, ), ( DiagnosticId::lint("invalid-argument-type"), Some("/src/tomllib/_parser.py"), Some(17319..17363), - "Argument to this function is incorrect", + "Argument to function `skip_until` is incorrect", Severity::Error, ), ]; diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/new_types.md b/crates/ty_python_semantic/resources/mdtest/annotations/new_types.md index 2fb342aeb4..5dc14964cc 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/new_types.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/new_types.md @@ -12,7 +12,7 @@ X = GenericAlias(type, ()) A = NewType("A", int) # TODO: typeshed for `typing.GenericAlias` uses `type` for the first argument. `NewType` should be special-cased # to be compatible with `type` -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `type`, found `NewType`" +# error: [invalid-argument-type] "Argument to function `__new__` is incorrect: Expected `type`, found `NewType`" B = GenericAlias(A, ()) def _( diff --git a/crates/ty_python_semantic/resources/mdtest/call/annotation.md b/crates/ty_python_semantic/resources/mdtest/call/annotation.md index 709ad8e1a6..937d4226fc 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/annotation.md +++ b/crates/ty_python_semantic/resources/mdtest/call/annotation.md @@ -9,8 +9,8 @@ def _(c: Callable[[], int]): def _(c: Callable[[int, str], int]): reveal_type(c(1, "a")) # revealed: int - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["a"]`" - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[1]`" + # error: [invalid-argument-type] "Argument is incorrect: Expected `int`, found `Literal["a"]`" + # error: [invalid-argument-type] "Argument is incorrect: Expected `str`, found `Literal[1]`" reveal_type(c("a", 1)) # revealed: int ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/callable_instance.md b/crates/ty_python_semantic/resources/mdtest/call/callable_instance.md index 9f43e7b621..d6e36e061f 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/callable_instance.md +++ b/crates/ty_python_semantic/resources/mdtest/call/callable_instance.md @@ -85,7 +85,7 @@ class C: c = C() -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to bound method `__call__` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(c("foo")) # revealed: int ``` @@ -99,7 +99,7 @@ class C: c = C() -# error: 13 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `C`" +# error: 13 [invalid-argument-type] "Argument to bound method `__call__` is incorrect: Expected `int`, found `C`" reveal_type(c()) # revealed: int ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/constructor.md b/crates/ty_python_semantic/resources/mdtest/call/constructor.md index 365da90b5e..e56fb09320 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/constructor.md +++ b/crates/ty_python_semantic/resources/mdtest/call/constructor.md @@ -99,8 +99,8 @@ def _(flag: bool) -> None: def __new__(cls, x: int, y: int = 1): ... reveal_type(Foo(1)) # revealed: Foo - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["1"]`" - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["1"]`" + # error: [invalid-argument-type] "Argument to function `__new__` is incorrect: Expected `int`, found `Literal["1"]`" + # error: [invalid-argument-type] "Argument to function `__new__` is incorrect: Expected `int`, found `Literal["1"]`" reveal_type(Foo("1")) # revealed: Foo # error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`" # error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`" @@ -232,8 +232,8 @@ def _(flag: bool) -> None: def __init__(self, x: int, y: int = 1): ... reveal_type(Foo(1)) # revealed: Foo - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["1"]`" - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["1"]`" + # error: [invalid-argument-type] "Argument to bound method `__init__` is incorrect: Expected `int`, found `Literal["1"]`" + # error: [invalid-argument-type] "Argument to bound method `__init__` is incorrect: Expected `int`, found `Literal["1"]`" reveal_type(Foo("1")) # revealed: Foo # error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`" # error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`" diff --git a/crates/ty_python_semantic/resources/mdtest/call/function.md b/crates/ty_python_semantic/resources/mdtest/call/function.md index 5a56f6c58d..e6e4771050 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/function.md +++ b/crates/ty_python_semantic/resources/mdtest/call/function.md @@ -77,7 +77,7 @@ def _(flag: bool): def f(x: int) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f("foo")) # revealed: int ``` @@ -87,7 +87,7 @@ reveal_type(f("foo")) # revealed: int def f(x: int, /) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f("foo")) # revealed: int ``` @@ -97,7 +97,7 @@ reveal_type(f("foo")) # revealed: int def f(*args: int) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f("foo")) # revealed: int ``` @@ -107,7 +107,7 @@ reveal_type(f("foo")) # revealed: int def f(x: int) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f(x="foo")) # revealed: int ``` @@ -117,7 +117,7 @@ reveal_type(f(x="foo")) # revealed: int def f(*, x: int) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f(x="foo")) # revealed: int ``` @@ -127,7 +127,7 @@ reveal_type(f(x="foo")) # revealed: int def f(**kwargs: int) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" reveal_type(f(x="foo")) # revealed: int ``` @@ -137,8 +137,8 @@ reveal_type(f(x="foo")) # revealed: int def f(x: int = 1, y: str = "foo") -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[2]`" -# error: 20 [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["bar"]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `str`, found `Literal[2]`" +# error: 20 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["bar"]`" reveal_type(f(y=2, x="bar")) # revealed: int ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md b/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md index 79b0c821d6..fc54aefd00 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md +++ b/crates/ty_python_semantic/resources/mdtest/call/getattr_static.md @@ -115,7 +115,7 @@ inspect.getattr_static() # error: [missing-argument] "No argument provided for required parameter `attr`" inspect.getattr_static(C()) -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[1]`" +# error: [invalid-argument-type] "Argument to function `getattr_static` is incorrect: Expected `str`, found `Literal[1]`" inspect.getattr_static(C(), 1) # error: [too-many-positional-arguments] "Too many positional arguments to function `getattr_static`: expected 3, got 4" diff --git a/crates/ty_python_semantic/resources/mdtest/call/invalid_syntax.md b/crates/ty_python_semantic/resources/mdtest/call/invalid_syntax.md index 81b933d7f5..3d88ff2ebf 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/invalid_syntax.md +++ b/crates/ty_python_semantic/resources/mdtest/call/invalid_syntax.md @@ -24,7 +24,7 @@ to the valid order: def f(**kw: int, x: str) -> int: return 1 -# error: 15 [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[1]`" +# error: 15 [invalid-argument-type] "Argument to function `f` is incorrect: Expected `str`, found `Literal[1]`" reveal_type(f(1)) # revealed: int ``` @@ -38,7 +38,7 @@ def f(x: int = 1, y: str) -> int: return 1 reveal_type(f(y="foo")) # revealed: int -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["foo"]`" +# error: [invalid-argument-type] "Argument to function `f` is incorrect: Expected `int`, found `Literal["foo"]`" # error: [missing-argument] "No argument provided for required parameter `y` of function `f`" reveal_type(f("foo")) # revealed: int ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/methods.md b/crates/ty_python_semantic/resources/mdtest/call/methods.md index c1b366749b..e6fde2e261 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/methods.md +++ b/crates/ty_python_semantic/resources/mdtest/call/methods.md @@ -350,7 +350,7 @@ class D: # This function is wrongly annotated, it should be `type[D]` instead of `D` pass -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `D`, found ``" +# error: [invalid-argument-type] "Argument to bound method `f` is incorrect: Expected `D`, found ``" D.f() ``` diff --git a/crates/ty_python_semantic/resources/mdtest/call/subclass_of.md b/crates/ty_python_semantic/resources/mdtest/call/subclass_of.md index 696d578d84..49b0967098 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/subclass_of.md +++ b/crates/ty_python_semantic/resources/mdtest/call/subclass_of.md @@ -20,7 +20,7 @@ class C: def _(subclass_of_c: type[C]): reveal_type(subclass_of_c(1)) # revealed: C - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["a"]`" + # error: [invalid-argument-type] "Argument to bound method `__init__` is incorrect: Expected `int`, found `Literal["a"]`" reveal_type(subclass_of_c("a")) # revealed: C # error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`" reveal_type(subclass_of_c()) # revealed: C diff --git a/crates/ty_python_semantic/resources/mdtest/call/union.md b/crates/ty_python_semantic/resources/mdtest/call/union.md index 3f891eaed1..5edbdb2981 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/union.md +++ b/crates/ty_python_semantic/resources/mdtest/call/union.md @@ -94,7 +94,7 @@ def _(flag: bool): else: f = f2 - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[3]`" + # error: [invalid-argument-type] "Argument to function `f2` is incorrect: Expected `str`, found `Literal[3]`" x = f(3) reveal_type(x) # revealed: int | str ``` diff --git a/crates/ty_python_semantic/resources/mdtest/decorators.md b/crates/ty_python_semantic/resources/mdtest/decorators.md index 2c947bd734..f92eca8003 100644 --- a/crates/ty_python_semantic/resources/mdtest/decorators.md +++ b/crates/ty_python_semantic/resources/mdtest/decorators.md @@ -207,7 +207,7 @@ first argument: def wrong_signature(f: int) -> str: return "a" -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `def f(x) -> Unknown`" +# error: [invalid-argument-type] "Argument to function `wrong_signature` is incorrect: Expected `int`, found `def f(x) -> Unknown`" @wrong_signature def f(x): ... diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md index f8dd3b3690..e009c137a3 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md @@ -99,9 +99,9 @@ def _(n: int): else: f = PossiblyNotCallable() # error: [too-many-positional-arguments] - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[3]`" + # error: [invalid-argument-type] "Argument to function `f2` is incorrect: Expected `str`, found `Literal[3]`" # error: [missing-argument] - # error: [invalid-argument-type] "Argument to this function is incorrect: Argument type `Literal[3]` does not satisfy upper bound of type variable `T`" + # error: [invalid-argument-type] "Argument to function `f4` is incorrect: Argument type `Literal[3]` does not satisfy upper bound of type variable `T`" # error: [call-non-callable] "Object of type `Literal[5]` is not callable" # error: [no-matching-overload] # error: [call-non-callable] "Object of type `PossiblyNotCallable` is not callable (possibly unbound `__call__` method)" diff --git a/crates/ty_python_semantic/resources/mdtest/doc/public_type_undeclared_symbols.md b/crates/ty_python_semantic/resources/mdtest/doc/public_type_undeclared_symbols.md index 72676dfbeb..50e73bef0f 100644 --- a/crates/ty_python_semantic/resources/mdtest/doc/public_type_undeclared_symbols.md +++ b/crates/ty_python_semantic/resources/mdtest/doc/public_type_undeclared_symbols.md @@ -42,7 +42,7 @@ def f(w: Wrapper) -> None: v: int | None = w.value # This function call is incorrect, because `w.value` could be `None`. We therefore emit the following - # error: "Argument to this function is incorrect: Expected `int`, found `Unknown | None`" + # error: "Argument to function `accepts_int` is incorrect: Expected `int`, found `Unknown | None`" c = accepts_int(w.value) ``` diff --git a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md index 2ddf11d0d1..e101384ce6 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md @@ -123,11 +123,11 @@ reveal_type(Bounded[int]()) # revealed: Bounded[int] reveal_type(Bounded[IntSubclass]()) # revealed: Bounded[IntSubclass] # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `str`" +# error: [invalid-argument-type] "Argument to class `Bounded` is incorrect: Expected `int`, found `str`" reveal_type(Bounded[str]()) # revealed: Unknown # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `int | str`" +# error: [invalid-argument-type] "Argument to class `Bounded` is incorrect: Expected `int`, found `int | str`" reveal_type(Bounded[int | str]()) # revealed: Unknown reveal_type(BoundedByUnion[int]()) # revealed: BoundedByUnion[int] @@ -156,7 +156,7 @@ reveal_type(Constrained[str]()) # revealed: Constrained[str] reveal_type(Constrained[int | str]()) # revealed: Constrained[int | str] # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int | str`, found `object`" +# error: [invalid-argument-type] "Argument to class `Constrained` is incorrect: Expected `int | str`, found `object`" reveal_type(Constrained[object]()) # revealed: Unknown ``` diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md index b85d0f8960..b342137e7f 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md @@ -98,11 +98,11 @@ reveal_type(Bounded[int]()) # revealed: Bounded[int] reveal_type(Bounded[IntSubclass]()) # revealed: Bounded[IntSubclass] # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `str`" +# error: [invalid-argument-type] "Argument to class `Bounded` is incorrect: Expected `int`, found `str`" reveal_type(Bounded[str]()) # revealed: Unknown # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `int | str`" +# error: [invalid-argument-type] "Argument to class `Bounded` is incorrect: Expected `int`, found `int | str`" reveal_type(Bounded[int | str]()) # revealed: Unknown reveal_type(BoundedByUnion[int]()) # revealed: BoundedByUnion[int] @@ -129,7 +129,7 @@ reveal_type(Constrained[str]()) # revealed: Constrained[str] reveal_type(Constrained[int | str]()) # revealed: Constrained[int | str] # TODO: update this diagnostic to talk about type parameters and specializations -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int | str`, found `object`" +# error: [invalid-argument-type] "Argument to class `Constrained` is incorrect: Expected `int | str`, found `object`" reveal_type(Constrained[object]()) # revealed: Unknown ``` diff --git a/crates/ty_python_semantic/resources/mdtest/generics/scoping.md b/crates/ty_python_semantic/resources/mdtest/generics/scoping.md index 0300cadc87..4376f1db0d 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/scoping.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/scoping.md @@ -84,7 +84,7 @@ class C[T]: c: C[int] = C[int]() c.m1(1) c.m2(1) -# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `int`, found `Literal["string"]`" +# error: [invalid-argument-type] "Argument to bound method `m2` is incorrect: Expected `int`, found `Literal["string"]`" c.m2("string") ``` diff --git a/crates/ty_python_semantic/resources/mdtest/properties.md b/crates/ty_python_semantic/resources/mdtest/properties.md index 2a24f2cd5f..aff91ead1b 100644 --- a/crates/ty_python_semantic/resources/mdtest/properties.md +++ b/crates/ty_python_semantic/resources/mdtest/properties.md @@ -146,7 +146,7 @@ class C: @property def attr(self) -> int: return 1 - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `(Any, Any, /) -> None`, found `def attr(self) -> None`" + # error: [invalid-argument-type] "Argument to bound method `setter` is incorrect: Expected `(Any, Any, /) -> None`, found `def attr(self) -> None`" @attr.setter def attr(self) -> None: pass @@ -156,7 +156,7 @@ class C: ```py class C: - # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `((Any, /) -> Any) | None`, found `def attr(self, x: int) -> int`" + # error: [invalid-argument-type] "Argument to class `property` is incorrect: Expected `((Any, /) -> Any) | None`, found `def attr(self, x: int) -> int`" @property def attr(self, x: int) -> int: return 1 diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_bound_typevar.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_bound_typevar.snap index cac47eee3e..c5db7e159d 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_bound_typevar.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_bound_typevar.snap @@ -68,7 +68,7 @@ info[revealed-type]: Revealed type ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f` is incorrect --> src/mdtest_snippet.py:12:15 | 10 | reveal_type(f(True)) # revealed: Literal[True] diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_constrained_typevar.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_constrained_typevar.snap index a934f8206d..c205f38f3f 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_constrained_typevar.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___Legacy_syntax_-_Inferring_a_constrained_typevar.snap @@ -83,7 +83,7 @@ info[revealed-type]: Revealed type ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f` is incorrect --> src/mdtest_snippet.py:13:15 | 11 | reveal_type(f(None)) # revealed: None diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_bound_typevar.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_bound_typevar.snap index 2900a6671d..87178f460d 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_bound_typevar.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_bound_typevar.snap @@ -65,7 +65,7 @@ info[revealed-type]: Revealed type ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f` is incorrect --> src/mdtest_snippet.py:9:15 | 7 | reveal_type(f(True)) # revealed: Literal[True] diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_constrained_typevar.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_constrained_typevar.snap index 57eb90a95f..a5f3b93c2d 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_constrained_typevar.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/functions.md_-_Generic_functions___PEP_695_syntax_-_Inferring_a_constrained_typevar.snap @@ -80,7 +80,7 @@ info[revealed-type]: Revealed type ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f` is incorrect --> src/mdtest_snippet.py:10:15 | 8 | reveal_type(f(None)) # revealed: None diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Basic.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Basic.snap index b6d8d86d25..8cebbee51e 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Basic.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Basic.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:5 | 2 | return x * x diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Calls_to_methods.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Calls_to_methods.snap index 1be0e562f1..8665bb6c74 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Calls_to_methods.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Calls_to_methods.snap @@ -23,7 +23,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to bound method `square` is incorrect --> src/mdtest_snippet.py:6:10 | 5 | c = C() diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_files.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_files.snap index 9293cf184e..e5b7be00b9 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_files.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_files.snap @@ -27,7 +27,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:3:13 | 1 | import package diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_source_order.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_source_order.snap index 29c466d3c3..a673f81a12 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_source_order.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Different_source_order.snap @@ -22,7 +22,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:2:9 | 1 | def bar(): diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters.snap index 7de8796083..f0b5a683cb 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:8 | 2 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_across_multiple_lines.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_across_multiple_lines.snap index f558144b07..e55a5c9dcf 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_across_multiple_lines.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_across_multiple_lines.snap @@ -25,7 +25,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:8:8 | 6 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_with_multiple_invalid_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_with_multiple_invalid_arguments.snap index 023fc78df1..22fa78f173 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_with_multiple_invalid_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Many_parameters_with_multiple_invalid_arguments.snap @@ -24,7 +24,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:7:5 | 5 | # error: [invalid-argument-type] @@ -44,7 +44,7 @@ info: `invalid-argument-type` is enabled by default ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:7:10 | 5 | # error: [invalid-argument-type] @@ -64,7 +64,7 @@ info: `invalid-argument-type` is enabled by default ``` ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:7:15 | 5 | # error: [invalid-argument-type] diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Test_calling_a_function_whose_type_is_vendored_from_`typeshed`.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Test_calling_a_function_whose_type_is_vendored_from_`typeshed`.snap index 1e1bdd1f17..bb31cfe7e9 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Test_calling_a_function_whose_type_is_vendored_from_`typeshed`.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Test_calling_a_function_whose_type_is_vendored_from_`typeshed`.snap @@ -20,7 +20,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `loads` is incorrect --> src/mdtest_snippet.py:3:12 | 1 | import json diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Keyword_only_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Keyword_only_arguments.snap index 2b8fba2de4..60f4937c29 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Keyword_only_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Keyword_only_arguments.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:11 | 2 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Mix_of_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Mix_of_arguments.snap index de4b2e16c2..e7779170d0 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Mix_of_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Mix_of_arguments.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:11 | 2 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_One_keyword_argument.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_One_keyword_argument.snap index fb6d69d999..7f93af33e2 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_One_keyword_argument.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_One_keyword_argument.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:11 | 2 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Only_positional.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Only_positional.snap index e222277fa9..2839c5399b 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Only_positional.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Only_positional.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:8 | 2 | return x * y * z diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Synthetic_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Synthetic_arguments.snap index e9d144d630..125d0b09d7 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Synthetic_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Synthetic_arguments.snap @@ -23,7 +23,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to bound method `__call__` is incorrect --> src/mdtest_snippet.py:6:3 | 5 | c = C() diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_arguments.snap index 7e18db62f5..dc4b6b73a5 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_arguments.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:14 | 2 | return len(numbers) diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_keyword_arguments.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_keyword_arguments.snap index 2b36d64363..da318f03e6 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_keyword_arguments.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid_argument_type.md_-_Invalid_argument_type_diagnostics_-_Tests_for_a_variety_of_argument_types_-_Variadic_keyword_arguments.snap @@ -21,7 +21,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/invalid_argu # Diagnostics ``` -error[invalid-argument-type]: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `foo` is incorrect --> src/mdtest_snippet.py:4:20 | 2 | return len(numbers) diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_A_smaller_scale_example.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_A_smaller_scale_example.snap index 092bd1a77b..130dca3db6 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_A_smaller_scale_example.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_A_smaller_scale_example.snap @@ -31,7 +31,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.m # Diagnostics ``` -error: lint:invalid-argument-type: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f2` is incorrect --> src/mdtest_snippet.py:14:11 | 12 | # error: [too-many-positional-arguments] @@ -48,12 +48,14 @@ info: Function defined here | ^^ --------- Parameter declared here 5 | return 0 | -info: `lint:invalid-argument-type` is enabled by default +info: Union variant `def f2(name: str) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int)` +info: `invalid-argument-type` is enabled by default ``` ``` -error: lint:too-many-positional-arguments: Too many positional arguments to function `f1`: expected 0, got 1 +error[too-many-positional-arguments]: Too many positional arguments to function `f1`: expected 0, got 1 --> src/mdtest_snippet.py:14:11 | 12 | # error: [too-many-positional-arguments] @@ -61,6 +63,8 @@ error: lint:too-many-positional-arguments: Too many positional arguments to func 14 | x = f(3) | ^ | -info: `lint:too-many-positional-arguments` is enabled by default +info: Union variant `def f1() -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int)` +info: `too-many-positional-arguments` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Multiple_variants_but_only_one_is_invalid.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Multiple_variants_but_only_one_is_invalid.snap index 3d27c3172a..61f3d7c0c5 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Multiple_variants_but_only_one_is_invalid.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Multiple_variants_but_only_one_is_invalid.snap @@ -30,7 +30,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.m # Diagnostics ``` -error: lint:invalid-argument-type: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f2` is incorrect --> src/mdtest_snippet.py:13:11 | 11 | f = f2 @@ -47,6 +47,8 @@ info: Function defined here | ^^ --------- Parameter declared here 5 | return 0 | -info: `lint:invalid-argument-type` is enabled by default +info: Union variant `def f2(name: str) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1(a: int) -> int) | (def f2(name: str) -> int)` +info: `invalid-argument-type` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_keyword_argument_related_reasons.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_keyword_argument_related_reasons.snap index 9e2b422427..82c3a86de9 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_keyword_argument_related_reasons.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_keyword_argument_related_reasons.snap @@ -31,7 +31,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.m # Diagnostics ``` -error: lint:parameter-already-assigned: Multiple values provided for parameter `name` of function `f1` +error[parameter-already-assigned]: Multiple values provided for parameter `name` of function `f1` --> src/mdtest_snippet.py:14:18 | 12 | # error: [parameter-already-assigned] @@ -39,12 +39,14 @@ error: lint:parameter-already-assigned: Multiple values provided for parameter ` 14 | y = f("foo", name="bar", unknown="quux") | ^^^^^^^^^^ | -info: `lint:parameter-already-assigned` is enabled by default +info: Union variant `def f1(name: str) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1(name: str) -> int) | (def any(*args, **kwargs) -> int)` +info: `parameter-already-assigned` is enabled by default ``` ``` -error: lint:unknown-argument: Argument `unknown` does not match any known parameter of function `f1` +error[unknown-argument]: Argument `unknown` does not match any known parameter of function `f1` --> src/mdtest_snippet.py:14:30 | 12 | # error: [parameter-already-assigned] @@ -52,6 +54,8 @@ error: lint:unknown-argument: Argument `unknown` does not match any known parame 14 | y = f("foo", name="bar", unknown="quux") | ^^^^^^^^^^^^^^ | -info: `lint:unknown-argument` is enabled by default +info: Union variant `def f1(name: str) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1(name: str) -> int) | (def any(*args, **kwargs) -> int)` +info: `unknown-argument` is enabled by default ``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_non-keyword_related_reasons.snap b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_non-keyword_related_reasons.snap index e66a8226f7..80b8aa2019 100644 --- a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_non-keyword_related_reasons.snap +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_function_types_-_Try_to_cover_all_possible_reasons_-_Cover_non-keyword_related_reasons.snap @@ -53,9 +53,9 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.m 39 | else: 40 | f = PossiblyNotCallable() 41 | # error: [too-many-positional-arguments] -42 | # error: [invalid-argument-type] "Argument to this function is incorrect: Expected `str`, found `Literal[3]`" +42 | # error: [invalid-argument-type] "Argument to function `f2` is incorrect: Expected `str`, found `Literal[3]`" 43 | # error: [missing-argument] -44 | # error: [invalid-argument-type] "Argument to this function is incorrect: Argument type `Literal[3]` does not satisfy upper bound of type variable `T`" +44 | # error: [invalid-argument-type] "Argument to function `f4` is incorrect: Argument type `Literal[3]` does not satisfy upper bound of type variable `T`" 45 | # error: [call-non-callable] "Object of type `Literal[5]` is not callable" 46 | # error: [no-matching-overload] 47 | # error: [call-non-callable] "Object of type `PossiblyNotCallable` is not callable (possibly unbound `__call__` method)" @@ -65,7 +65,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.m # Diagnostics ``` -error: lint:call-non-callable: Object of type `Literal[5]` is not callable +error[call-non-callable]: Object of type `Literal[5]` is not callable --> src/mdtest_snippet.py:48:9 | 46 | # error: [no-matching-overload] @@ -73,12 +73,14 @@ error: lint:call-non-callable: Object of type `Literal[5]` is not callable 48 | x = f(3) | ^^^^ | -info: `lint:call-non-callable` is enabled by default +info: Union variant `Literal[5]` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `call-non-callable` is enabled by default ``` ``` -error: lint:call-non-callable: Object of type `PossiblyNotCallable` is not callable (possibly unbound `__call__` method) +error[call-non-callable]: Object of type `PossiblyNotCallable` is not callable (possibly unbound `__call__` method) --> src/mdtest_snippet.py:48:9 | 46 | # error: [no-matching-overload] @@ -86,12 +88,14 @@ error: lint:call-non-callable: Object of type `PossiblyNotCallable` is not calla 48 | x = f(3) | ^^^^ | -info: `lint:call-non-callable` is enabled by default +info: Union variant `PossiblyNotCallable` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `call-non-callable` is enabled by default ``` ``` -error: lint:missing-argument: No argument provided for required parameter `b` of function `f3` +error[missing-argument]: No argument provided for required parameter `b` of function `f3` --> src/mdtest_snippet.py:48:9 | 46 | # error: [no-matching-overload] @@ -99,12 +103,14 @@ error: lint:missing-argument: No argument provided for required parameter `b` of 48 | x = f(3) | ^^^^ | -info: `lint:missing-argument` is enabled by default +info: Union variant `def f3(a: int, b: int) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `missing-argument` is enabled by default ``` ``` -error: lint:no-matching-overload: No overload of method wrapper `__get__` of function `f` matches arguments +error[no-matching-overload]: No overload of method wrapper `__get__` of function `f` matches arguments --> src/mdtest_snippet.py:48:9 | 46 | # error: [no-matching-overload] @@ -112,12 +118,14 @@ error: lint:no-matching-overload: No overload of method wrapper `__get__` of fun 48 | x = f(3) | ^^^^ | -info: `lint:no-matching-overload` is enabled by default +info: Union variant `` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `no-matching-overload` is enabled by default ``` ``` -error: lint:invalid-argument-type: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f2` is incorrect --> src/mdtest_snippet.py:48:11 | 46 | # error: [no-matching-overload] @@ -134,12 +142,14 @@ info: Function defined here | ^^ --------- Parameter declared here 7 | return 0 | -info: `lint:invalid-argument-type` is enabled by default +info: Union variant `def f2(name: str) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `invalid-argument-type` is enabled by default ``` ``` -error: lint:invalid-argument-type: Argument to this function is incorrect +error[invalid-argument-type]: Argument to function `f4` is incorrect --> src/mdtest_snippet.py:48:11 | 46 | # error: [no-matching-overload] @@ -156,12 +166,14 @@ info: Type variable defined here | ^^^^^^ 13 | return 0 | -info: `lint:invalid-argument-type` is enabled by default +info: Union variant `def f4(x: T) -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `invalid-argument-type` is enabled by default ``` ``` -error: lint:too-many-positional-arguments: Too many positional arguments to function `f1`: expected 0, got 1 +error[too-many-positional-arguments]: Too many positional arguments to function `f1`: expected 0, got 1 --> src/mdtest_snippet.py:48:11 | 46 | # error: [no-matching-overload] @@ -169,6 +181,8 @@ error: lint:too-many-positional-arguments: Too many positional arguments to func 48 | x = f(3) | ^ | -info: `lint:too-many-positional-arguments` is enabled by default +info: Union variant `def f1() -> int` is incompatible with this call site +info: Attempted to call union type `(def f1() -> int) | (def f2(name: str) -> int) | (def f3(a: int, b: int) -> int) | (def f4(x: T) -> int) | Literal[5] | Unknown | () | PossiblyNotCallable` +info: `too-many-positional-arguments` is enabled by default ``` diff --git a/crates/ty_python_semantic/src/types/call/bind.rs b/crates/ty_python_semantic/src/types/call/bind.rs index 28803bd902..d20c5e2faa 100644 --- a/crates/ty_python_semantic/src/types/call/bind.rs +++ b/crates/ty_python_semantic/src/types/call/bind.rs @@ -24,7 +24,7 @@ use crate::types::{ FunctionType, KnownClass, KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType, TupleType, UnionType, WrapperDescriptorKind, }; -use ruff_db::diagnostic::{Annotation, Severity, SubDiagnostic}; +use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic}; use ruff_python_ast as ast; /// Binding information for a possible union of callables. At a call site, the arguments must be @@ -199,8 +199,19 @@ impl<'db> Bindings<'db> { } } + // If this is not a union, then report a diagnostic for any + // errors as normal. + if let Some(binding) = self.single_element() { + binding.report_diagnostics(context, node, None); + return; + } + for binding in self { - binding.report_diagnostics(context, node); + let union_diag = UnionDiagnostic { + callable_type: self.callable_type(), + binding, + }; + binding.report_diagnostics(context, node, Some(&union_diag)); } } @@ -1043,23 +1054,34 @@ impl<'db> CallableBinding<'db> { Type::unknown() } - fn report_diagnostics(&self, context: &InferContext<'db>, node: ast::AnyNodeRef) { + fn report_diagnostics( + &self, + context: &InferContext<'db>, + node: ast::AnyNodeRef, + union_diag: Option<&UnionDiagnostic<'_, '_>>, + ) { if !self.is_callable() { if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Object of type `{}` is not callable", self.callable_type.display(context.db()), )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } return; } if self.dunder_call_is_possibly_unbound { if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Object of type `{}` is not callable (possibly unbound `__call__` method)", self.callable_type.display(context.db()), )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } return; } @@ -1067,7 +1089,7 @@ impl<'db> CallableBinding<'db> { let callable_description = CallableDescription::new(context.db(), self.callable_type); if self.overloads.len() > 1 { if let Some(builder) = context.report_lint(&NO_MATCHING_OVERLOAD, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "No overload{} matches arguments", if let Some(CallableDescription { kind, name }) = callable_description { format!(" of {kind} `{name}`") @@ -1075,6 +1097,9 @@ impl<'db> CallableBinding<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } return; } @@ -1086,6 +1111,7 @@ impl<'db> CallableBinding<'db> { node, self.signature_type, callable_description.as_ref(), + union_diag, ); } } @@ -1385,9 +1411,10 @@ impl<'db> Binding<'db> { node: ast::AnyNodeRef, callable_ty: Type<'db>, callable_description: Option<&CallableDescription>, + union_diag: Option<&UnionDiagnostic<'_, '_>>, ) { for error in &self.errors { - error.report_diagnostic(context, node, callable_ty, callable_description); + error.report_diagnostic(context, node, callable_ty, callable_description, union_diag); } } @@ -1539,12 +1566,13 @@ pub(crate) enum BindingError<'db> { } impl<'db> BindingError<'db> { - pub(super) fn report_diagnostic( + fn report_diagnostic( &self, context: &InferContext<'db>, node: ast::AnyNodeRef, callable_ty: Type<'db>, callable_description: Option<&CallableDescription>, + union_diag: Option<&UnionDiagnostic<'_, '_>>, ) { match self { Self::InvalidArgumentType { @@ -1561,7 +1589,14 @@ impl<'db> BindingError<'db> { let provided_ty_display = provided_ty.display(context.db()); let expected_ty_display = expected_ty.display(context.db()); - let mut diag = builder.into_diagnostic("Argument to this function is incorrect"); + let mut diag = builder.into_diagnostic(format_args!( + "Argument{} is incorrect", + if let Some(CallableDescription { kind, name }) = callable_description { + format!(" to {kind} `{name}`") + } else { + String::new() + } + )); diag.set_primary_message(format_args!( "Expected `{expected_ty_display}`, found `{provided_ty_display}`" )); @@ -1575,6 +1610,9 @@ impl<'db> BindingError<'db> { ); diag.sub(sub); } + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } Self::TooManyPositionalArguments { @@ -1584,7 +1622,7 @@ impl<'db> BindingError<'db> { } => { let node = Self::get_node(node, *first_excess_argument_index); if let Some(builder) = context.report_lint(&TOO_MANY_POSITIONAL_ARGUMENTS, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Too many positional arguments{}: expected \ {expected_positional_count}, got {provided_positional_count}", if let Some(CallableDescription { kind, name }) = callable_description { @@ -1593,13 +1631,16 @@ impl<'db> BindingError<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } } Self::MissingArguments { parameters } => { if let Some(builder) = context.report_lint(&MISSING_ARGUMENT, node) { let s = if parameters.0.len() == 1 { "" } else { "s" }; - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "No argument{s} provided for required parameter{s} {parameters}{}", if let Some(CallableDescription { kind, name }) = callable_description { format!(" of {kind} `{name}`") @@ -1607,6 +1648,9 @@ impl<'db> BindingError<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } } @@ -1616,7 +1660,7 @@ impl<'db> BindingError<'db> { } => { let node = Self::get_node(node, *argument_index); if let Some(builder) = context.report_lint(&UNKNOWN_ARGUMENT, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Argument `{argument_name}` does not match any known parameter{}", if let Some(CallableDescription { kind, name }) = callable_description { format!(" of {kind} `{name}`") @@ -1624,6 +1668,9 @@ impl<'db> BindingError<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } } @@ -1633,7 +1680,7 @@ impl<'db> BindingError<'db> { } => { let node = Self::get_node(node, *argument_index); if let Some(builder) = context.report_lint(&PARAMETER_ALREADY_ASSIGNED, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Multiple values provided for parameter {parameter}{}", if let Some(CallableDescription { kind, name }) = callable_description { format!(" of {kind} `{name}`") @@ -1641,6 +1688,9 @@ impl<'db> BindingError<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } } @@ -1657,7 +1707,14 @@ impl<'db> BindingError<'db> { let argument_type = error.argument_type(); let argument_ty_display = argument_type.display(context.db()); - let mut diag = builder.into_diagnostic("Argument to this function is incorrect"); + let mut diag = builder.into_diagnostic(format_args!( + "Argument{} is incorrect", + if let Some(CallableDescription { kind, name }) = callable_description { + format!(" to {kind} `{name}`") + } else { + String::new() + } + )); diag.set_primary_message(format_args!( "Argument type `{argument_ty_display}` does not satisfy {} of type variable `{}`", match error { @@ -1671,12 +1728,15 @@ impl<'db> BindingError<'db> { let mut sub = SubDiagnostic::new(Severity::Info, "Type variable defined here"); sub.annotate(Annotation::primary(typevar_range.into())); diag.sub(sub); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } Self::InternalCallError(reason) => { let node = Self::get_node(node, None); if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) { - builder.into_diagnostic(format_args!( + let mut diag = builder.into_diagnostic(format_args!( "Call{} failed: {reason}", if let Some(CallableDescription { kind, name }) = callable_description { format!(" of {kind} `{name}`") @@ -1684,6 +1744,9 @@ impl<'db> BindingError<'db> { String::new() } )); + if let Some(union_diag) = union_diag { + union_diag.add_union_context(context.db(), &mut diag); + } } } } @@ -1708,3 +1771,39 @@ impl<'db> BindingError<'db> { } } } + +/// Contains additional context for union specific diagnostics. +/// +/// This is used when a function call is inconsistent with one or more variants +/// of a union. This can be used to attach sub-diagnostics that clarify that +/// the error is part of a union. +struct UnionDiagnostic<'b, 'db> { + /// The type of the union. + callable_type: Type<'db>, + /// The specific binding that failed. + binding: &'b CallableBinding<'db>, +} + +impl UnionDiagnostic<'_, '_> { + /// Adds context about any relevant union function types to the given + /// diagnostic. + fn add_union_context(&self, db: &'_ dyn Db, diag: &mut Diagnostic) { + let sub = SubDiagnostic::new( + Severity::Info, + format_args!( + "Union variant `{callable_ty}` is incompatible with this call site", + callable_ty = self.binding.callable_type.display(db), + ), + ); + diag.sub(sub); + + let sub = SubDiagnostic::new( + Severity::Info, + format_args!( + "Attempted to call union type `{}`", + self.callable_type.display(db) + ), + ); + diag.sub(sub); + } +}