pyrefly icon indicating copy to clipboard operation
pyrefly copied to clipboard

Non-ReadOnly TypedDict fields should behave invariantly in subtyping

Open JelleZijlstra opened this issue 7 months ago • 1 comments

Describe the Bug

from typing import Any, Dict

from typing_extensions import ReadOnly, TypedDict

class TD(TypedDict):
    a: int

class TD2(TypedDict):
    a: ReadOnly[int]

class TD3(TypedDict):
    a: bool

def want_td(td: TD) -> None:
    pass

def capybara(
    td: TD, td2: TD2, td3: TD3
) -> None:
    want_td(td2)  # E: incompatible_argument
    want_td(td3)  # E: incompatible_argument

Both of the want_td calls should be rejected. A TypedDict with a ReadOnly[X] key is not assignable to one with an equivalent X key, because the latter allows assignment. For similar reasons, all (non-ReadOnly) items should be treated as invariant in assignability checks.

Sandbox Link

https://pyrefly.org/sandbox/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMoCCKcANFACJIDGMAULaJLIqmgPoCmAHjBygM5IwAzNlz4AShwCGAEwDyKADakoAFUQdZlGvSpLp-fuvIAKDQi06YASgBctKE6jS7mFHVr7DxteQBM5pra1LYOzi5uUnKKKgDaqDAAunoGRiYAzEGWITT2js6uUABGYGBK9LIcwFAA7tIebDCyps1ufjZQALQAfFAAcsIc4c4IPpXVUFTSCHDF0iDSpgVObSZkzf7tARuyGdsZtJ29A0MjTvWNza2y-p1QAMRQAKJuqFSQYzBIxUocbAs0ABXCB8OgRS4wJotZoZe5PV7uD7YaTfX7-QEgsG0IA

(Only applicable for extension issues) IDE Information

No response

JelleZijlstra avatar May 22 '25 05:05 JelleZijlstra

This should (hopefully) be a fairly quick fix in is_subset_eq, i'll leave it around for another week or two in case a new contributor wants to take a stab at it, otherwise I'll pick it up myself.

yangdanny97 avatar May 30 '25 16:05 yangdanny97

@yangdanny97 For the good first issue tag, are there any pointers we could give for where to start looking at the changes that need to be made?

connernilsen avatar Jun 10 '25 19:06 connernilsen

@connernilsen the change would involve adding an is_subset_eq in the opposite direction for non-readonly fields here:

https://github.com/facebook/pyrefly/blob/08fa989ff8e4a0a781f51d03dedc33c090c62d20/pyrefly/lib/solver/subset.rs#L723

yangdanny97 avatar Jun 12 '25 03:06 yangdanny97