Skip to content

Commit 5ca254e

Browse files
committed
Updated draft based on initial round of feedback.
1 parent bab532e commit 5ca254e

File tree

1 file changed

+73
-53
lines changed

1 file changed

+73
-53
lines changed

docs/spec/overload.rst

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -124,27 +124,32 @@ Type checkers should enforce the following rules for overload definitions.
124124
At least two ``@overload``-decorated definitions must be present. If only
125125
one is present, an error should be reported.
126126

127-
An overload implementation should be present for all overload function
128-
definitions. Type checkers should report an error or warning if an
129-
implementation is missing. Overload definitions within stub files,
130-
protocols, and abstract base classes are exempt from this check.
127+
The ``@overload``-decorated definitions must be followed by an overload
128+
implementation, which does not include an ``@overload`` decorator. Type
129+
checkers should report an error or warning if an implementation is missing.
130+
Overload definitions within stub files, protocols, and abstract base classes
131+
are exempt from this check.
131132

132133
If an overload is decorated with ``@staticmethod`` or ``@classmethod``,
133134
all overloads must be similarly decorated. The implementation,
134-
if present, must be decorated in the same manner. Similarly, if one overload
135-
is ``async``, all overloads must be ``async`` as well as the implementation.
136-
Type checkers should report an error if these conditions are not met.
135+
if present, must be decorated in the same manner. Type checkers should report
136+
an error if these conditions are not met.
137137

138-
If one or more overloads are decorated with ``@final`` but the
138+
If one or more overloads are decorated with ``@final`` or ``@override`` but the
139139
implementation is not, an error should be reported.
140140

141+
Overloads are allowed to use a mixture of ``async def`` and ``def`` statements
142+
within the same overload definition. Type checkers should desugar all
143+
``async def`` statements before testing for implementation consistency
144+
and overlapping overloads (described below).
145+
141146

142147
Implementation consistency
143148
^^^^^^^^^^^^^^^^^^^^^^^^^^
144149

145150
If an overload implementation is defined, type checkers should validate
146-
that its signature is consistent with all of its associated overload
147-
signatures. The implementation should accept all potential argument lists
151+
that it is consistent with all of its associated overload signatures.
152+
The implementation should accept all potential sets of arguments
148153
that are accepted by the overloads and should produce all potential return
149154
types produced by the overloads. In typing terms, this means the input
150155
signature of the implementation should be assignable to the input signatures
@@ -166,22 +171,36 @@ should report an error::
166171
def func(x: int | str, /) -> str:
167172
return str(x)
168173

174+
When a type checker checks the implementation for consistency with overloads,
175+
it should first apply any transforms that change the effective type of the
176+
implementation including the presence of a ``yield`` statement in the
177+
implementation body, the use of ``async def``, and the presence of additional
178+
decorators.
179+
180+
169181
Overlapping overloads
170182
^^^^^^^^^^^^^^^^^^^^^
171183

172-
If two overloads can accept the same set of arguments but have
173-
different return types, the overloads are said to "partially overlap".
174-
This condition is indicative of a programming error and should
175-
be reported by type checkers::
184+
If two overloads can accept the same set of arguments, they are said
185+
to "partially overlap". If two overloads partially overlap, the return type
186+
of the latter overload should be assignable to the return type of the
187+
former overload. If this condition doesn't hold, it is indicative of a
188+
programming error and should be reported by type checkers::
176189

177190
# These overloads partially overlap because both accept an
178191
# argument of type ``Literal[0]``, but their return types
179192
# differ.
180193

181194
@overload
182-
def func(x: Literal[0]) -> int: ...
195+
def func1(x: Literal[0]) -> int: ...
183196
@overload
184-
def func(x: int) -> str: ...
197+
def func1(x: int) -> str: ...
198+
199+
[Eric's note for reviewers: Mypy exempts `__get__` from the above check.
200+
Refer to https://github.com/python/typing/issues/253#issuecomment-389262904
201+
for Ivan's explanation. I'm not convinced this exemption is necessary.
202+
Currently pyright copies the exemption. Do we want to codify this or leave it
203+
out?]
185204

186205
If all arguments accepted by an overload are also always accepted by
187206
an earlier overload, the two overloads are said to "fully overlap".
@@ -218,7 +237,7 @@ input signatures.
218237

219238
- If no candidate overloads remain, generate an error and stop.
220239
- If only one candidate overload remains, it is the winning match. Evaluate
221-
it as if it were a non-overloaded function call and stop.
240+
it as if it were a non-overloaded function call and stop.
222241
- If two or more candidate overloads remain, proceed to step 2.
223242

224243

@@ -230,7 +249,7 @@ Simply record which of the overloads result in evaluation errors.
230249

231250
- If all overloads result in errors, proceed to step 3.
232251
- If only one overload evaluates without error, it is the winning match.
233-
Evaluate it as if it were a non-overloaded function call and stop.
252+
Evaluate it as if it were a non-overloaded function call and stop.
234253
- If two or more candidate overloads remain, proceed to step 4.
235254

236255

@@ -253,11 +272,12 @@ After each argument expansion, return to step 2 and evaluate all
253272
expanded argument lists.
254273

255274
- If all argument lists evaluate successfully, combine their
256-
respective return types by union to determine the final return type
257-
for the call, and stop.
275+
respective return types by union to determine the final return type
276+
for the call, and stop.
258277
- If argument expansion has been applied to all arguments and one or
259-
more of the expanded argument lists cannot be evaluated successfully,
260-
generate an error and stop.
278+
more of the expanded argument lists cannot be evaluated successfully,
279+
generate an error and stop.
280+
261281

262282
For additional details about argument type expansion, see
263283
:ref:`argument-type-expansion` below.
@@ -270,29 +290,30 @@ that supplies an indeterminate number of positional or keyword arguments.
270290
If so, eliminate overloads that do not have a variadic parameter.
271291

272292
- If this results in only one remaining candidate overload, it is
273-
the winning match. Evaluate it as if it were a non-overloaded function
274-
call and stop.
293+
the winning match. Evaluate it as if it were a non-overloaded function
294+
call and stop.
275295
- If two or more candidate overloads remain, proceed to step 5.
276296

277297

278298
Step 5: If the type of one or more arguments evaluates to a
279-
:ref:`gradual type` (e.g. ``list[Any]`` or ``str | Any``), determine
280-
whether some theoretical :ref:`materialization` of these gradual types
281-
could be used to disambiguate between two or more of the remaining
282-
overloads.
299+
type that includes a :term:`gradual form` (e.g. ``list[Any]`` or
300+
``str | Any``), determine whether some theoretical
301+
:ref:`materialization` of these gradual types could be used to disambiguate
302+
between two or more of the remaining overloads.
283303

284304
- If none of the arguments evaluate to a gradual type, proceed to step 6.
285305
- If one or more arguments evaluate to a gradual type but no possible
286-
materializations of these types would disambiguate between the remaining
287-
overloads, proceed to step 6.
306+
materializations of these types would disambiguate between the remaining
307+
overloads, proceed to step 6.
288308
- If possible materializations of these types would disambiguate between
289-
two or more of the remaining overloads and this subset of overloads have
290-
consistent return types, proceed to step 6. If the return types include
291-
type variables, constraint solving should be applied here before testing
292-
for consistency.
309+
two or more of the remaining overloads and this subset of overloads have
310+
consistent return types, proceed to step 6. If the return types include
311+
type variables, constraint solving should be applied here before testing
312+
for consistency.
293313
- If none of the above conditions are met, the presence of gradual types
294-
leads to an ambiguous overload selection. Assume a return type of ``Any``
295-
and stop. This preserves the "gradual guarantee".
314+
leads to an ambiguous overload selection. Assume a return type of ``Any``
315+
and stop. This preserves the "gradual guarantee".
316+
296317

297318
[Eric's note for reviewers: I'm struggling to come up with an
298319
understandable and unambiguous way to describe this step.
@@ -386,27 +407,19 @@ Example 4::
386407
def example4(x: int, y: int) -> list[int]: ...
387408

388409
def test(v1: list[Any], v2: Any):
389-
# Step 4 eliminates third overload. Step 5
390-
# determines that first and second overloads
391-
# both apply and are ambiguous due to Any, but
392-
# return types are consistent.
393-
r1 = example4(v1, 1)
394-
reveal_type(r1) # Should reveal int
395-
396-
# Step 4 eliminates third overload. Step 5
410+
# Step 2 eliminates the third overload. Step 5
397411
# determines that first and second overloads
398412
# both apply and are ambiguous due to Any, but
399413
# return types are consistent.
400-
r2 = example4([1], v2)
401-
reveal_type(r2) # Should reveal int
402-
403-
# Step 5 determines that first, second, and third
404-
# overloads all apply and are ambiguous due to Any.
405-
# These have inconsistent return types, so evaluated
406-
# type is Any.
407-
r3 = example4(v2, v2)
408-
reveal_type(r3) # Should reveal Any
414+
r1 = example4(v1, v2)
415+
reveal_type(r1) # Reveals int
409416

417+
# Step 2 eliminates the second overload. Step 5
418+
# determines that first and third overloads
419+
# both apply and are ambiguous due to Any, and
420+
# the return types are inconsistent.
421+
r2 = example4(v2, 1)
422+
reveal_type(r2) # Should reveal Any
410423

411424

412425
Argument type expansion
@@ -482,3 +495,10 @@ complexity to call evaluations and would likely result in a measurable slowdown
482495
in type evaluation, but it's worth considering. We could perhaps mitigate the
483496
slowdown by applying this behavior only when a constrained type variable is
484497
used in the call's signature.]
498+
499+
[Eric's note for reviewers: What about expansion based on multiple inheritance?
500+
For example, if class C inherits from A and B, should we expand C into A and B
501+
for purposes of overload matching? This could get very expensive and difficult
502+
to spec, and it feels like a significant edge case, so I'm inclined to leave it
503+
out. No one has asked for this, to my knowledge.]
504+

0 commit comments

Comments
 (0)