Skip to content

Commit 56d630e

Browse files
authored
[ty] Enums: allow multiple aliases to point to the same member (#20669)
## Summary closes astral-sh/ty#1293 ## Test Plan Regression test
1 parent 963bc8c commit 56d630e

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

crates/ty_python_semantic/resources/mdtest/enums.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,41 @@ reveal_type(enum_members(Color))
265265
reveal_type(Color.red)
266266
```
267267

268+
Multiple aliases to the same member are also supported. This is a regression test for
269+
<https://github.com/astral-sh/ty/issues/1293>:
270+
271+
```py
272+
from ty_extensions import enum_members
273+
274+
class ManyAliases(Enum):
275+
real_member = "real_member"
276+
alias1 = "real_member"
277+
alias2 = "real_member"
278+
alias3 = "real_member"
279+
280+
other_member = "other_real_member"
281+
282+
# revealed: tuple[Literal["real_member"], Literal["other_member"]]
283+
reveal_type(enum_members(ManyAliases))
284+
285+
reveal_type(ManyAliases.real_member) # revealed: Literal[ManyAliases.real_member]
286+
reveal_type(ManyAliases.alias1) # revealed: Literal[ManyAliases.real_member]
287+
reveal_type(ManyAliases.alias2) # revealed: Literal[ManyAliases.real_member]
288+
reveal_type(ManyAliases.alias3) # revealed: Literal[ManyAliases.real_member]
289+
290+
reveal_type(ManyAliases.real_member.value) # revealed: Literal["real_member"]
291+
reveal_type(ManyAliases.real_member.name) # revealed: Literal["real_member"]
292+
293+
reveal_type(ManyAliases.alias1.value) # revealed: Literal["real_member"]
294+
reveal_type(ManyAliases.alias1.name) # revealed: Literal["real_member"]
295+
296+
reveal_type(ManyAliases.alias2.value) # revealed: Literal["real_member"]
297+
reveal_type(ManyAliases.alias2.name) # revealed: Literal["real_member"]
298+
299+
reveal_type(ManyAliases.alias3.value) # revealed: Literal["real_member"]
300+
reveal_type(ManyAliases.alias3.name) # revealed: Literal["real_member"]
301+
```
302+
268303
### Using `auto()`
269304

270305
```toml

crates/ty_python_semantic/src/types/enums.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,19 @@ pub(crate) fn enum_metadata<'db>(
194194
// we don't know if it's a duplicate or not.
195195
if matches!(
196196
value_ty,
197-
Type::IntLiteral(_) | Type::StringLiteral(_) | Type::BytesLiteral(_)
197+
Type::BooleanLiteral(_)
198+
| Type::IntLiteral(_)
199+
| Type::StringLiteral(_)
200+
| Type::BytesLiteral(_)
198201
) {
199-
if let Some(previous) = enum_values.insert(value_ty, name.clone()) {
200-
aliases.insert(name.clone(), previous);
202+
if let Some(canonical) = enum_values.get(&value_ty) {
203+
// This is a duplicate value, create an alias to the canonical (first) member
204+
aliases.insert(name.clone(), canonical.clone());
201205
return None;
202206
}
207+
208+
// This is the first occurrence of this value, track it as the canonical member
209+
enum_values.insert(value_ty, name.clone());
203210
}
204211

205212
let declarations = use_def_map.end_of_scope_symbol_declarations(symbol_id);

0 commit comments

Comments
 (0)