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.
https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0BBdKQA0dADIQGMSqihiAcjABuMsblWUouVJjGUVMOQH0mxGAB10VgAIaZ23VcwwwdLFwAUcABapziIwArsSwANpKmmIAVAwh4ZFqdIQpALqpAJR0ALQAfJzoDIEphLb2WjqYzq7umF6%2B-jCBcaEwYawMmTn5ktKyUGEAjKnFKWWajlVYNR403n4Bwa3thWIdXXkSUjJyYQBMI8lj6HYTldVus-ONzfFtHWIlG-kdo6XTl3VzDYst4Q9HQjPApFKx0cF0AxxSjoOiwdDXcwZKwoj50Fw0XDGNiyTBBOTeW7LISiQGZRBgiEGVQmMwwTxXOAZLJ0ADEdAAqugANboXAAd1hELonhg%2BHMAGNpJhAh1kdY0Risbh0PS4ET-oVyZTwdSjFBTMx6YzmeD2b0dgNhuDPAB5ADS8ou6JgmNM-NwhKWmoYay1GQpQt1hlpRoZX28prZWz6uwONodTsVrqxylQlAguggEq9f3uqzJAZ1kJDBrp4fqUfZHWFtbtjqsIBEICCDGgcBI5EQIHZHLbUCkpDoYCC6ClEBVcFRLjcYF4NFQDGM6CCNGwMk8%2BFlhSymzgDEogeFUKCMOHFhAClX68PdGA%2BAAvhfG82yAYwFBSIQGLQoBR2QACqQ76fnQaBYHg%2BB0BKKqQGwp6LhO6DvOyADKMAwHQPgMAwxDqgA9Phb6uJ%2BhC8Gw%2BEwOg%2BGYLgEpwPhMHoHBCFtiq%2BHDrwdCoGm0CoNgsDQbBEDwbIbGwrgxDiR2VhkAwPgqtkmhwEhdAALx0BeADMhCDHsz7oCAD7Nqg46qAAYtAMAUOBOAEJ2RlAA
In
demo_gradualI would have expected it to eithertuple[Never, ...]overload, sincetuple[Any, ...](and onlytuple[Any, ...]) is assignable totuple[Never, ...](this matches pyright), orintin this case. This would be more in line with the typing spec.Either way, I expected
tuple[Any, ...]to result in anint.But instead, it returns
Unknown, which makes me thing that none of the overloads match.The other three overloads are behaving correctly.