Improving type support for math.prod
#13572
8000
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Related to #13501
The existing
prod
type stub did not properly support types likeFraction
,complex
, andDecimal
provided by Python. To address this, I attempted to define the type stub in a way similar tobuiltins.sum
.Before
Limitations
The previous type stub only checked for
__index__
or__float__
, but I believe this approach is entirely incorrect. There is no code inmath_prod_impl
that calls__index__
or__float__
. As a result, the following cases fail:Additionally, the old stub did not account for empty iterables:
After
This implementation is largely derived from
sum
, so it shares the same limitations. You can find related PRs forsum
here: #7578 and #8000.Since those PRs were created in 2022, I tried different ways to improve this using newer typing features introduced since then, but none worked out. If anyone has a better idea, I'd love to hear it!
Improvements
With this change,
prod
correctly handles cases like:Limitations
This implementation still produces many false positives. Non-numeric types in Python use the multiplication operator in many different ways due to syntactic sugar, which makes precise typing pretty difficult.
prod("abcde")
str | Literal[1]
prod([1, 2, 3], start="a")
str
int | str
prod([2], start=(1, 2))
(1, 2, 1, 2)
tuple
int | tuple[Literal[1], Literal[2]]