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 92423187a7..2b08cc94be 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md @@ -184,3 +184,22 @@ def _(x: T, y: int) -> T: # error: [invalid-argument-type] return x.foo(y) ``` + +## Union with overloaded method and incompatible variant + +When calling a method on a union type where: + +- One variant has the method with compatible arguments (`str.split`) +- Another variant has the method but with incompatible arguments (`bytes.split` expects `Buffer`, + not `str`) +- Other variants don't have the method at all (contributing `Unknown` to the callable) + +We should only report the specific error for the incompatible variant (`invalid-argument-type` for +`bytes.split`), not a spurious `no-matching-overload` for the compatible variant. + +```py +def _(x: bytes | str | int): + # error: [invalid-argument-type] + # error: [possibly-missing-attribute] + x.split(" ") +``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_f…_-_Union_with_overloade…_(4408ade1316b97c0).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_f…_-_Union_with_overloade…_(4408ade1316b97c0).snap new file mode 100644 index 0000000000..59310b22d1 --- /dev/null +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/union_call.md_-_Calling_a_union_of_f…_-_Union_with_overloade…_(4408ade1316b97c0).snap @@ -0,0 +1,59 @@ +--- +source: crates/ty_test/src/lib.rs +expression: snapshot +--- + +--- +mdtest name: union_call.md - Calling a union of function types - Union with overloaded method and incompatible variant +mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/union_call.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | def _(x: bytes | str | int): +2 | # error: [invalid-argument-type] +3 | # error: [possibly-missing-attribute] +4 | x.split(" ") +``` + +# Diagnostics + +``` +warning[possibly-missing-attribute]: Attribute `split` may be missing on object of type `bytes | str | int` + --> src/mdtest_snippet.py:4:5 + | +2 | # error: [invalid-argument-type] +3 | # error: [possibly-missing-attribute] +4 | x.split(" ") + | ^^^^^^^ + | +info: rule `possibly-missing-attribute` is enabled by default + +``` + +``` +error[invalid-argument-type]: Argument to bound method `split` is incorrect + --> src/mdtest_snippet.py:4:13 + | +2 | # error: [invalid-argument-type] +3 | # error: [possibly-missing-attribute] +4 | x.split(" ") + | ^^^ Expected `Buffer | None`, found `Literal[" "]` + | +info: Method defined here + --> stdlib/builtins.pyi:1761:9 + | +1759 | """ +1760 | +1761 | def split(self, sep: ReadableBuffer | None = None, maxsplit: SupportsIndex = -1) -> list[bytes]: + | ^^^^^ --------------------------------- Parameter declared here +1762 | """Return a list of the sections in the bytes, using sep as the delimiter. + | +info: Union variant `bound method bytes.split(sep: Buffer | None = None, maxsplit: SupportsIndex = -1) -> list[bytes]` is incompatible with this call site +info: Attempted to call union type `(bound method bytes.split(sep: Buffer | None = None, maxsplit: SupportsIndex = -1) -> list[bytes]) | (Overload[(sep: LiteralString | None = None, maxsplit: SupportsIndex = -1) -> list[LiteralString], (sep: str | None = None, maxsplit: SupportsIndex = -1) -> list[str]])` +info: rule `invalid-argument-type` 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 978bdbf842..dd41fe781c 100644 --- a/crates/ty_python_semantic/src/types/call/bind.rs +++ b/crates/ty_python_semantic/src/types/call/bind.rs @@ -327,6 +327,9 @@ impl<'db> Bindings<'db> { } for binding in self { + if binding.as_result().is_ok() { + continue; + } let union_diag = UnionDiagnostic { callable_type: self.callable_type(), binding,