Skip to content

Commit ee90846

Browse files
authored
[ty] fix PEP 695 type aliases in with statement (#24395)
1 parent 2f839db commit ee90846

2 files changed

Lines changed: 44 additions & 4 deletions

File tree

crates/ty_python_semantic/resources/mdtest/with/sync.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,46 @@ def _(flag: bool):
4040
reveal_type(f) # revealed: str | int
4141
```
4242

43+
## Type aliases preserve context manager behavior
44+
45+
```toml
46+
[environment]
47+
python-version = "3.12"
48+
```
49+
50+
```py
51+
from typing import Self, TypeAlias
52+
from typing_extensions import TypeAliasType
53+
54+
class A:
55+
def __enter__(self) -> Self:
56+
return self
57+
58+
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
59+
60+
class B:
61+
def __enter__(self) -> Self:
62+
return self
63+
64+
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
65+
66+
UnionAB1: TypeAlias = A | B
67+
type UnionAB2 = A | B
68+
UnionAB3 = TypeAliasType("UnionAB3", A | B)
69+
70+
def f1(x: UnionAB1) -> None:
71+
with x as y:
72+
reveal_type(y) # revealed: A | B
73+
74+
def f2(x: UnionAB2) -> None:
75+
with x as y:
76+
reveal_type(y) # revealed: A | B
77+
78+
def f3(x: UnionAB3) -> None:
79+
with x as y:
80+
reveal_type(y) # revealed: A | B
81+
```
82+
4383
## Context manager without an `__enter__` or `__exit__` method
4484

4585
```py

crates/ty_python_semantic/src/types.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,10 @@ impl<'db> Type<'db> {
32853285
.member_lookup_with_policy(db, name, policy)
32863286
}
32873287

3288+
Type::TypeAlias(alias) => alias
3289+
.value_type(db)
3290+
.member_lookup_with_policy(db, name, policy),
3291+
32883292
_ if policy.no_instance_fallback() => self.invoke_descriptor_protocol(
32893293
db,
32903294
name_str,
@@ -3293,10 +3297,6 @@ impl<'db> Type<'db> {
32933297
policy,
32943298
),
32953299

3296-
Type::TypeAlias(alias) => alias
3297-
.value_type(db)
3298-
.member_lookup_with_policy(db, name, policy),
3299-
33003300
Type::LiteralValue(literal)
33013301
if literal.as_enum().is_some()
33023302
&& matches!(name_str, "name" | "_name_" | "value" | "_value_") =>

0 commit comments

Comments
 (0)