facebook / facebook/pyrefly

Method parameters of constrained TypeVars are not narrowed in function with multiple generic variables

Open
#3,621 3 comments 2 reactions 0 assignees View on GitHub
typechecking
Dominant language
Rust
Stars
7k
Forks
519
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

This was a hard one to title.

I am trying to type my Polars DataFrame function code to support to similar kinds of dataframes, and I have a minimal working example. `DataFrame` is an in-memory object, while a `LazyFrame` is not. They cannot be joined together, but have a lot of similar methods. Two DataFrames or two LazyFrames can be joined.

It is a common pattern to write functions that are generic over these two types, always returning the same type, e.g.

```python
from typing import TypeVar
import polars as pl

Frame = TypeVar("Frame", pl.DataFrame, pl.LazyFrame)

def join_them(df1: Frame, df2: Frame) -> Frame:
return df1.join(df2)
```
or, equivalently in the modern syntax:

```python
def join_them[Frame: (pl.DataFrame, pl.LazyFrame)](df1: Frame, df2: Frame) -> Frame:
return df1.join(df2)
```

I get a type error here, demonstrated more easily using [this sandbox](https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0AVZjABqqSgB10UgMR0AQgFd%2BACxiUYdAJJ1c2OOoBumhitT9TmtjHTqIAYzic46AOT9i1YqjbmYmRhVqRTYVQM0aGFNcTDhEOgADACtcVgB9SxoEujBUaDhCKXsoVDgnABFzVAAxSlRIxCk6ZrpMGDA6FNYACgMoMAAaXUtKeMqGGrrIgEo6AFoAPjpxyfqYRvQWrboNBkVKTb6wKSKSsroAGVQAL1JatY2tto6u9F6YfqHcEfir2-uZvMln87lN1k1ts1dvtDh9jtJ0ADNABeQTCMSUboSEBI7FDFZIoYgpHTE5YdqdVLoDJqGjdMC4XDxQl0bDiZlg6aPFrQg45RmEV7dNmUWZyAA8cylczoAFFKNRRnQAIKUNiKSLofgJJHZCBOdDfOilOAQNjoVDYWCMXB0bxghjqRLfNSUbIAdwgpkYwkSBLBes2YEU6HsDAguE2CX9a0FVISZLkWg6OiYxAipDokWisRtdEUBmNWB2URhdAAynChpZNl66O7eABrOBDbDKQL6uhwFS4RRQTBufjYTQaACOiggGkwGzA1HoadYHC4PD4FbhZOKJuWVSRACZuc1npSekcvj81-1ZosL2B4hLpTeIZDebD%2Bhuzk5iWD90-WhShaewyuvElaXkCN53nQkpSo%2BmyQiWex8kcZJInQqJCOmGJYjiYJ4tuEx7kSNygmsu6kgiR6vDSMB0gyTJ0CyIocmsXK-i%2B-K4HGPQitMIADCAZAaGAUCkIQDC0FAFByAACqQQkiV2GA4AQdD2JGkDqnU4aRoU6ByJWmgqAwDDEHEAD0ZmCe0ImELwbBmTYZmYLgjhmWp6Aafs5gRugZn8pQxqGHkJRWpo7meVpPm6MQ2noAUUhkNE6BzMYlCmpGaF0NiADMhAAIy7tiUgANrqIqcAALpSCGy68I6mBzJgk4wGGEDGJlrhmoaGiuFIhoMHMY4TlOcyNjApBzKg9j2PATioq47riG4UggAAvvxU3hsY1TQDAFBoFgeBEGQa1AA).

Interestingly, if I type the return type on my `def join` methods as `Self`, then it passes type checking, but I think this is an unnecessary restriction.

### Sandbox Link

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0AVZjABqqSgB10UgMR0AQgFd%2BACxiUYdAJJ1c2OOoBumhitT9TmtjHTqIAYzic46AOT9i1YqjbmYmRhVqRTYVQM0aGFNcTDhEOgADACtcVgB9SxoEujBUaDhCKXsoVDgnABFzVAAxSlRIxCk6ZrpMGDA6FNYACgMoMAAaXUtKeMqGGrrIgEo6AFoAPjpxyfqYRvQWrboNBkVKTb6wKSKSsroAGVQAL1JatY2tto6u9F6YfqHcEfir2-uZvMln87lN1k1ts1dvtDh9jtJ0ADNABeQTCMSUboSEBI7FDFZIoYgpHTE5YdqdVLoDJqGjdMC4XDxQl0bDiZlg6aPFrQg45RmEV7dNmUWZyAA8cylczoAFFKNRRnQAIKUNiKSLofgJJHZCBOdDfOilOAQNjoVDYWCMXB0bxghjqRLfNSUbIAdwgpkYwkSBLBes2YEU6HsDAguE2CX9a0FVISZLkWg6OiYxAipDokWisRtdEUBmNWB2URhdAAynChpZNl66O7eABrOBDbDKQL6uhwFS4RRQTBufjYTQaACOiggGkwGzA1HoadYHC4PD4FbhZOKJuWVSRACZuc1npSekcvj81-1ZosL2B4hLpTeIZDebD%2Bhuzk5iWD90-WhShaewyuvElaXkCN53nQkpSo%2BmyQiWex8kcZJInQqJCOmGJYjiYJ4tuEx7kSNygmsu6kgiR6vDSMB0gyTJ0CyIocmsXK-i%2B-K4HGPQitMIADCAZAaGAUCkIQDC0FAFByAACqQQkiV2GA4AQdD2JGkDqnU4aRoU6ByJWmgqAwDDEHEAD0ZmCe0ImELwbBmTYZmYLgjhmWp6Aafs5gRugZn8pQxqGHkJRWpo7meVpPm6MQ2noAUUhkNE6BzMYlCmpGaF0NiADMhAAIy7tiUgANrqIqcAALpSCGy68I6mBzJgk4wGGEDGJlrhmoaGiuFIhoMHMY4TlOcyNjApBzKg9j2PATioq47riG4UggAAvvxU3hsY1TQDAFBoFgeBEGQa1AA

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.