Skip to content

unexpected tuple[] behavior #2235

@jorenham

Description

@jorenham
from typing import Any, Literal, Never, overload, reveal_type

@overload
def ndim(shape: tuple[Never, ...]) -> int: ...
@overload
def ndim(shape: tuple[int]) -> Literal[1]: ...
@overload
def ndim(shape: tuple[int, int]) -> Literal[2]: ...
@overload
def ndim(shape: tuple[int, ...]) -> int: ...
def ndim(shape: tuple[int, ...]) -> int:
    return len(shape)


def demo_gradual(s: tuple[Any, ...]):
    reveal_type(ndim(s))  # Unknown     (expected: int)

def demo_one(s: tuple[int]):
    reveal_type(ndim(s))  # Literal[1]  (OK)

def demo_two(s: tuple[int, int]):
    reveal_type(ndim(s))  # Literal[2]  (OK)

def demo_variadic(s: tuple[int, ...]):
    reveal_type(ndim(s))  # int         (OK)

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0BBdKQA0dADIQGMSqihiAcjABuMsblWUouVJjGUVMOQH0mxGAB10VgAIaZ23VcwwwdLFwAUcABapziIwArsSwANpKmmIAVAwh4ZFqdIQpALqpAJR0ALQAfJzoDIEphLb2WjqYzq7umF6%2B-jCBcaEwYawMmTn5ktKyUGEAjKnFKWWajlVYNR403n4Bwa3thWIdXXkSUjJyYQBMI8lj6HYTldVus-ONzfFtHWIlG-kdo6XTl3VzDYst4Q9HQjPApFKx0cF0AxxSjoOiwdDXcwZKwoj50Fw0XDGNiyTBBOTeW7LISiQGZRBgiEGVQmMwwTxXOAZLJ0ADEdAAqugANboXAAd1hELonhg%2BHMAGNpJhAh1kdY0Risbh0PS4ET-oVyZTwdSjFBTMx6YzmeD2b0dgNhuDPAB5ADS8ou6JgmNM-NwhKWmoYay1GQpQt1hlpRoZX28prZWz6uwONodTsVrqxylQlAguggEq9f3uqzJAZ1kJDBrp4fqUfZHWFtbtjqsIBEICCDGgcBI5EQIHZHLbUCkpDoYCC6ClEBVcFRLjcYF4NFQDGM6CCNGwMk8%2BFlhSymzgDEogeFUKCMOHFhAClX68PdGA%2BAAvhfG82yAYwFBSIQGLQoBR2QACqQ76fnQaBYHg%2BB0BKKqQGwp6LhO6DvOyADKMAwHQPgMAwxDqgA9Phb6uJ%2BhC8Gw%2BEwOg%2BGYLgEpwPhMHoHBCFtiq%2BHDrwdCoGm0CoNgsDQbBEDwbIbGwrgxDiR2VhkAwPgqtkmhwEhdAALx0BeADMhCDHsz7oCAD7Nqg46qAAYtAMAUOBOAEJ2RlAA

In demo_gradual I would have expected it to either

  • match the first tuple[Never, ...] overload, since tuple[Any, ...] (and only tuple[Any, ...]) is assignable to tuple[Never, ...] (this matches pyright), or
  • match all overloads and return the intersection of the results, which would be int in this case. This would be more in line with the typing spec.

Either way, I expected tuple[Any, ...] to result in an int.

But instead, it returns Unknown, which makes me thing that none of the overloads match.

The other three overloads are behaving correctly.

Metadata

Metadata

Assignees

Labels

needs-discussionAn issue where it's not clear whether there is a bug or we are behaving as expected.typecheckingwontfixThis will not be worked on

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions