Skip to content

Commit 5a6d1a8

Browse files
migeed-zmeta-codesync[bot]
authored andcommitted
Document remaining conformance gaps
Summary: Here, we document dataclasses and context managers gaps Reviewed By: grievejia Differential Revision: D91739630 fbshipit-source-id: 2fe21672fed76136d9d8bd4db68f5d00e5c9bfb0
1 parent 41e3e6b commit 5a6d1a8

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

pyrefly/lib/test/dataclasses.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,3 +1694,63 @@ assert_type(c.x, int)
16941694
assert_type(c.y, int)
16951695
"#,
16961696
);
1697+
1698+
testcase!(
1699+
bug = "conformance: Dataclass with generic non-data descriptor should work correctly",
1700+
test_dataclass_generic_descriptor_conformance,
1701+
r#"
1702+
from dataclasses import dataclass
1703+
from typing import Any, Generic, TypeVar, assert_type, overload
1704+
1705+
T = TypeVar("T")
1706+
1707+
class Desc2(Generic[T]):
1708+
@overload
1709+
def __get__(self, instance: None, owner: Any) -> list[T]: ...
1710+
@overload
1711+
def __get__(self, instance: object, owner: Any) -> T: ...
1712+
def __get__(self, instance: object | None, owner: Any) -> list[T] | T: ...
1713+
1714+
@dataclass
1715+
class DC2:
1716+
x: Desc2[int]
1717+
y: Desc2[str]
1718+
z: Desc2[str] = Desc2() # E: Cannot set field `z` to non-data descriptor `Desc2`
1719+
1720+
# pyrefly incorrectly returns Desc2[T] instead of list[T] for class attribute access
1721+
assert_type(DC2.x, list[int]) # E: assert_type(Desc2[int], list[int]) failed
1722+
assert_type(DC2.y, list[str]) # E: assert_type(Desc2[str], list[str]) failed
1723+
1724+
dc2 = DC2(Desc2(), Desc2(), Desc2())
1725+
# pyrefly incorrectly returns Desc2[T] instead of T for instance attribute access
1726+
assert_type(dc2.x, int) # E: assert_type(Desc2[int], int) failed
1727+
assert_type(dc2.y, str) # E: assert_type(Desc2[str], str) failed
1728+
"#,
1729+
);
1730+
1731+
testcase!(
1732+
bug = "conformance: Dataclass with slots=True should error when setting undeclared attributes",
1733+
test_dataclass_slots_undeclared_attr_conformance,
1734+
r#"
1735+
from dataclasses import dataclass
1736+
1737+
@dataclass(slots=True)
1738+
class DC2:
1739+
x: int
1740+
1741+
def __init__(self):
1742+
self.x = 3
1743+
# should error: y is not in slots
1744+
self.y = 3
1745+
1746+
@dataclass(slots=False)
1747+
class DC3:
1748+
x: int
1749+
__slots__ = ("x",)
1750+
1751+
def __init__(self):
1752+
self.x = 3
1753+
# should error: y is not in slots
1754+
self.y = 3
1755+
"#,
1756+
);

pyrefly/lib/test/with.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,39 @@ with Foo() as foo:
323323
assert_type(foo, int)
324324
"#,
325325
);
326+
327+
testcase!(
328+
bug = "conformance: Context manager with bool/__exit__ should not narrow type after raise in if block",
329+
test_context_manager_exception_suppression_conformance,
330+
r#"
331+
from typing import Any, Literal, assert_type
332+
333+
class CMBase:
334+
def __enter__(self) -> None:
335+
pass
336+
337+
class Suppress1(CMBase):
338+
def __exit__(self, exc_type, exc_value, traceback) -> bool:
339+
return True
340+
341+
class Suppress2(CMBase):
342+
def __exit__(self, exc_type, exc_value, traceback) -> Literal[True]:
343+
return True
344+
345+
# When __exit__ returns bool or Literal[True], exceptions may be suppressed
346+
# so we should NOT narrow x based on the raise
347+
def suppress1(x: int | str) -> None:
348+
if isinstance(x, int):
349+
with Suppress1():
350+
raise ValueError
351+
# pyrefly incorrectly narrows x to str here, but exception might be suppressed
352+
assert_type(x, int | str) # E: assert_type(str, int | str) failed
353+
354+
def suppress2(x: int | str) -> None:
355+
if isinstance(x, int):
356+
with Suppress2():
357+
raise ValueError
358+
# pyrefly incorrectly narrows x to str here, but exception might be suppressed
359+
assert_type(x, int | str) # E: assert_type(str, int | str) failed
360+
"#,
361+
);

0 commit comments

Comments
 (0)