Non-ReadOnly TypedDict fields should behave invariantly in subtyping
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
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 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 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