Skip to content

Conversation

@johnslavik
Copy link
Member

@johnslavik johnslavik commented Jan 8, 2026

Follow-up to gh-130309.
See https://github.com/python/cpython/pull/130309/changes#r2663516538.

Details

These functions don't annotate parameters for values used in single-dispatching (item), they annotate parameters one later (arg).

This being legal relies on a bug -- GH-84644, which is that singledispatch doesn't verify the annotation is on the "first" parameter.

In practice, it doesn't matter how you annotate func here, because it's a default callback. But what matters is that any function passed to register() annotates the target parameter (always first positional in singledispatch and always second positional in singledispatchmethod (unless staticmethod, then the first) etc.) for the value to single-dispatch on; not some other, unrelated parameter (or return type, as presented in GH-84644).

Let's have a class with the same registree signature as these from the test:

class A:
    @functools.singledispatchmethod
    def func(self, item, arg: int) -> str:
        return 'argint'
    @func.register
    def _(self, item, arg: bytes) -> str:
        return 'argbytes'

a = A()
print(a.func(b'', 1))

For this code, the output would be argbytes, even though arg is an integer 1.

… the right params

See https://github.com/python/cpython/pull/130309/changes#r2663516538.

These functions don't annotate parameters for values used in single-dispatching (`item`), they annotate parameters one later (`arg`).

This being legal relies on a bug -- pythonGH-84644, which is that `singledispatch` doesn't verify the annotation is on the "first" parameter.
I think these functions should look like

```diff
            @functools.singledispatchmethod
-           def func(self, item, arg: int) -> str:
+           def func(self, item: int, arg) -> str:
                return str(item)
            @func.register
-           def _(self, item, arg: bytes) -> str:
+           def _(self, item: bytes, arg) -> str:
                return str(item)
```

(and signature tests updated accordingly)

In practice, it doesn't matter how you annotate `func` here, because it's a default callback. But what matters is that any function passed to `register()` annotates the target parameter (always first positional in `singledispatch` and always second positional in `singledispatchmethod` (unless staticmethod, then the first) etc.) for the value to single-dispatch on; not some other, unrelated parameter (or return type, as presented in pythonGH-84644).

Let's have a class with the same registree signature as these from the test:

```py
class A:
    @functools.singledispatchmethod
    def func(self, item, arg: int) -> str:
        return 'argint'
    @func.register
    def _(self, item, arg: bytes) -> str:
        return 'argbytes'

a = A()
print(a.func(b'', 1))
```

For this code, the output would be `argbytes`, even though `arg` is an integer `1`.
@johnslavik
Copy link
Member Author

@serhiy-storchaka, did I get it correctly? Thanks for the quick review :)

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 👍

@serhiy-storchaka serhiy-storchaka merged commit 620a5b9 into python:main Jan 11, 2026
48 checks passed
@miss-islington-app
Copy link

Thanks @johnslavik for the PR, and @serhiy-storchaka for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jan 11, 2026
…sts (pythonGH-143571)

These tests relied on a bug -- pythongh-84644, which is that singledispatch
doesn't verify the annotation is on the "first" parameter.
(cherry picked from commit 620a5b92693ac1b2cef1f90fd3c2dba1bb794552)

Co-authored-by: Bartosz Sławecki <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Jan 11, 2026

GH-143707 is a backport of this pull request to the 3.14 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jan 11, 2026
…sts (pythonGH-143571)

These tests relied on a bug -- pythongh-84644, which is that singledispatch
doesn't verify the annotation is on the "first" parameter.
(cherry picked from commit 620a5b9)

Co-authored-by: Bartosz Sławecki <[email protected]>
@bedevere-app bedevere-app bot removed the needs backport to 3.14 bugs and security fixes label Jan 11, 2026
@bedevere-app
Copy link

bedevere-app bot commented Jan 11, 2026

GH-143708 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Jan 11, 2026
serhiy-storchaka pushed a commit that referenced this pull request Jan 11, 2026
…ests (GH-143571) (GH-143708)

These tests relied on a bug -- gh-84644, which is that singledispatch
doesn't verify the annotation is on the "first" parameter.
(cherry picked from commit 620a5b9)

Co-authored-by: Bartosz Sławecki <[email protected]>
serhiy-storchaka pushed a commit that referenced this pull request Jan 11, 2026
…ests (GH-143571) (GH-143707)

These tests relied on a bug -- gh-84644, which is that singledispatch
doesn't verify the annotation is on the "first" parameter.
(cherry picked from commit 620a5b9)

Co-authored-by: Bartosz Sławecki <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip news tests Tests in the Lib/test dir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants