Skip to content

PEP 718: Specify binding, parametrisation and overload interactions#4649

Open
Gobot1234 wants to merge 8 commits intopython:mainfrom
Gobot1234:pep-718-even-more-updates
Open

PEP 718: Specify binding, parametrisation and overload interactions#4649
Gobot1234 wants to merge 8 commits intopython:mainfrom
Gobot1234:pep-718-even-more-updates

Conversation

@Gobot1234
Copy link
Copy Markdown
Contributor

@Gobot1234 Gobot1234 commented Oct 8, 2025

  • Change is either:
    • To a Draft PEP
    • To an Accepted or Final PEP, with Steering Council approval
    • To fix an editorial issue (markup, typo, link, header, etc)
  • PR title prefixed with PEP number (e.g. PEP 123: Summary of changes)

📚 Documentation preview 📚: https://pep-previews--4649.org.readthedocs.build/

@Gobot1234 Gobot1234 requested a review from gvanrossum as a code owner October 8, 2025 15:10
@python-cla-bot
Copy link
Copy Markdown

python-cla-bot bot commented Oct 8, 2025

All commit authors signed the Contributor License Agreement.

CLA signed

@Gobot1234
Copy link
Copy Markdown
Contributor Author

Gobot1234 commented Oct 8, 2025

Please can someone get the CLA bot to re-run? I'm not sure why it's requesting that email TBH. I've already signed it for my email gobot1234yt@gmail.com

Sorry I can't test I can't get make installed
@defjaf
Copy link
Copy Markdown

defjaf commented Oct 8, 2025

I don't think that the word "subscription" is being used correctly.

@hugovk
Copy link
Copy Markdown
Member

hugovk commented Oct 8, 2025

Please can someone get the CLA bot to re-run? I'm not sure why it's requesting that email TBH. I've already signed it for my email gobot1234yt@gmail.com

You committed with your Git client configured with that email, see https://github.com/python/peps/pull/4649.patch

You also need to sign it with that.

Comment thread peps/pep-0718.rst Outdated
the runtime type. The only change is that more situations will be decidable and the
behaviour/overload can be specified by the developer rather than leaving it to ordering
of overloads/unions.
Overloaded functions should work much the same as they already do, since they do not
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this is about the runtime behavior of calling overloaded functions?

Comment thread peps/pep-0718.rst Outdated
of overloads/unions.
Overloaded functions should work much the same as they already do, since they do not
affect the runtime type. Explicit specialisation will restrict the set of available
overloads.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's worth spelling out in detail how this would work. What I'd expect is that if the function is subscripted, only those overloads are considered for which the subscription may succeed. So if you have an overload make[*Ts], one with make[T], and one with just make, then a call to make[int] will only consider the first and second, and a call to make[int, str] will only consider the first. This could be another step in the overload resolution spec before all the current steps.

Comment thread peps/pep-0718.rst Outdated
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
@PabloRuizCuevas
Copy link
Copy Markdown

PabloRuizCuevas commented Nov 4, 2025

@Gobot1234 please if you need help don't hesitate to ask, I'm very interested on this feature and would be a pity to see it abandoned

@PabloRuizCuevas
Copy link
Copy Markdown

@JelleZijlstra Is there something I can do to move the needle on this PEP if the original author don't reply in a reasonable amount of time? like contributing to the writing of this PEP?

@JelleZijlstra
Copy link
Copy Markdown
Member

@Gobot1234 is still around, I'd wait a bit longer. But this PEP has been sitting for a long time and as I've written on Discuss before, I personally have some reservations about it. If you're interested in renewing the discussion and addressing the concerns that have been raised about the PEP, you could work with James to improve the PEP, or even write your own replacement PEP.

@PabloRuizCuevas
Copy link
Copy Markdown

@JelleZijlstra I already wrote James in Discourse, in GitHub and in private offering my help on September, after that he did reappear (but didn't particularly requested my help).

Now is almost a month without updates from him and I would really like to see this coming in python 3.15 (if is approved etc ofc), given that he did vanish for more than a year last time (look in discourse the message of Guido on 7 May 2023), I think is reasonable to move forward with the PEP after almost a month without updates from him. So how can I do my own PEP replacement / edit this? Would I count with your sponsorship or the original one from @gvanrossum ?

thanks in advance

@JelleZijlstra
Copy link
Copy Markdown
Member

You'd need a new sponsor. I'm not currently interested in sponsoring a version of this PEP, but another core dev might be.

@Gobot1234
Copy link
Copy Markdown
Contributor Author

@PabloRuizCuevas I'm happy to review stuff for it and would happily add you as a co-author. I just don't really have the time/motivation to finish it as my usage of python is so little nowadays

@gvanrossum
Copy link
Copy Markdown
Member

Alas, I can't take on sponsoring a new PEP either. But I will continue to fulfill my promises on the old one.

As a sponsor, I have to ask: what are the chances that the Typing Council will approve this PEP? That's the first and most important hurdle for typing PEPs.

@PabloRuizCuevas
Copy link
Copy Markdown

Ok I will help @Gobot1234 on finishing this one, @JelleZijlstra answering the concerns of Guido, and given that you belong to the typing council (right?), do you think that this PEP has any chance of being approved? If there is chances what would be the priority changes for me to make to advance on it. thanks in advance.

I guess the overload resolution as you already pointed out is one of them, right? anything else? I was planning to add other examples, motivations and ideas that were mentioned in discourse.

@JelleZijlstra
Copy link
Copy Markdown
Member

I don't know what the Typing Council will decide but I wrote this last year: https://discuss.python.org/t/pep-718-subscriptable-functions/28457/38 and still feel the motivation for the PEP is weak.

@hugovk
Copy link
Copy Markdown
Member

hugovk commented Feb 25, 2026

Lint is failing but the logs have expired. I've updated from main to get a fresh run.

Where are we up to with this PEP?

Reminder that the 3.15 feature freeze of 2026-05-05 is drawing near, and before this, the PEP will need:

  • to be finished
  • sent to the Typing Council for a recommendation
  • sent to the Steering Council for a decision
  • implemented and merged into CPython

Otherwise 3.16 is always an option.

@Gobot1234 Gobot1234 requested a review from JelleZijlstra March 5, 2026 11:22
@Gobot1234
Copy link
Copy Markdown
Contributor Author

@gvanrossum @JelleZijlstra would one of you mind reviewing this when you get the chance :)

I'm not really expecting it to make the 3.15 cut off but I'd still like to carry on moving forward with this.

Copy link
Copy Markdown
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

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

Left a few comments. As before I find a lot of the use cases dubious so I'm not the best person to advocate for this change.

Comment thread peps/pep-0718.rst Outdated
Comment thread peps/pep-0718.rst

.. code-block:: python

NameNumberDict = dict[str, int]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
NameNumberDict = dict[str, int]
NameNumberDict: dict[str, int]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh sorry this is not what you meant. I think this example would be clearer as something like name_number_dict = dict[str, int](one=1, ...)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine to keep this example exactly as it is.

Comment thread peps/pep-0718.rst
C[int].method[str](0, "") # OK
C[int].cls[str](0, "") # OK
C.cls[int, str](0, "") # Invalid: too many type parameters
C.cls[str](0, "") # OK, T is ideally bound to int here though this is open for type checkers to decide
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What else should type checkers do? Infer Literal[0]?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume @JelleZijlstra meant "What else could type checkers do?" I guess another option would be Any if the binding is done as soon as C.cls is seen (C not subscripted). Also if T had a default it could legally be used in preference over inferring from the call? (I'm fuzzy about this myself.)

Comment thread peps/pep-0718.rst

def foo[T](x: Sequence[T] | T) -> list[T]: ...

reveal_type(foo[bytes](b"hello"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But if you'd write foo[int](b"hello") it would also type check, right? So this is inherently unsound.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, this isn't a good motivational example. The bytes | Sequence[int] and str | Sequence[str] ambiguities need solutions elsewhere (and I don't know how I'd do it).

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Copy link
Copy Markdown
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Despite leaving a bunch of comments, I would be okay with merging this now so readers of the PEP have a newer version available, and split hairs in a follow-up PR. (PRs are cheap.)

Comment thread peps/pep-0718.rst

.. code-block:: python

NameNumberDict = dict[str, int]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine to keep this example exactly as it is.

Comment thread peps/pep-0718.rst

.. code-block:: python

def my_list[T](arr) -> list[T]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be augmented with arr: Iterable[T] (which reflects what list(arr) expects) or is that a distraction?

Comment thread peps/pep-0718.rst
def make_list[T](*args: T) -> list[T]: ...
reveal_type(make_list()) # type checker cannot infer a meaningful type for T
class my_list[T]:
def __call__(self, *args: T) -> list[T]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, this signature is inconsistent with make_list(arr) above.

Comment thread peps/pep-0718.rst

my_integer_list = my_list[int]() # TypeError: 'function' object is not subscriptable

There are a few workarounds:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think both examples would benefit from an example call of the resulting make_list() too. This seems esp. important for (2), which would reveal the clumsiness of that solution for callers.

Comment thread peps/pep-0718.rst
my_integer_list: list[int] = my_list()

This solution isn't optimal as the return type is repeated and is more verbose and
would require the type updating in multiple places if the return type changes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Additionally, it's verbose when the intention is to pass the specialized value into another call -- now the reader has to deal with the distraction of seeing a temporary variable declaration.

Comment thread peps/pep-0718.rst
the runtime type. The only change is that more situations will be decidable and the
behaviour/overload can be specified by the developer rather than leaving it to ordering
of overloads/unions.
This PEP opens the door to overloading based on type variables:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given the complexity and ambiguity already present in @overload I'm not sure that "opens the door" is enough of a specification.

Comment thread peps/pep-0718.rst
def spam[*T](bar: Bar[*T]): ...

This PEP does not allow functions like ``foo`` to be subscripted, for the same reason
as defined in :pep:`PEP 646<646#multiple-type-variable-tuples-not-allowed>`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That reason is so simple to explain that I'd just repeat it here. Also make it explicit that spam is acceptable here (rather than waiting to show it in the example below).

Comment thread peps/pep-0718.rst

Binding Rules
^^^^^^^^^^^^^
Method subscription (including ``classmethods``, ``staticmethods``, etc.) should only
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is covered by the casual "etc." here? In a spec it need to specified, not left as a guess for the reader based on an example.

Comment thread peps/pep-0718.rst
Binding Rules
^^^^^^^^^^^^^
Method subscription (including ``classmethods``, ``staticmethods``, etc.) should only
have access to their function's type parameter and not the enclosing class's.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
have access to their function's type parameter and not the enclosing class's.
allow their function's type parameters and not the enclosing class's.

Comment thread peps/pep-0718.rst
C[int].method[str](0, "") # OK
C[int].cls[str](0, "") # OK
C.cls[int, str](0, "") # Invalid: too many type parameters
C.cls[str](0, "") # OK, T is ideally bound to int here though this is open for type checkers to decide
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume @JelleZijlstra meant "What else could type checkers do?" I guess another option would be Any if the binding is done as soon as C.cls is seen (C not subscripted). Also if T had a default it could legally be used in preference over inferring from the call? (I'm fuzzy about this myself.)

@gvanrossum
Copy link
Copy Markdown
Member

@Gobot1234 Let me know your preference about how to proceed. I can promise to quickly merge what you have (including my suggestion) -- I can't promise to do another big review soon.

FWIW After a conversation with Claude I'm feeling more and more confident that we should do this. The counter-arguments "you don't need this" and "you can already do this with other means" don't convince me it's a bad idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants