mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-01 12:25:45 +00:00
[ty] Delegate truthiness inference of an enum Literal type to its enum-instance supertype (#21060)
This commit is contained in:
parent
e196c2ab37
commit
bf74c824eb
3 changed files with 37 additions and 12 deletions
|
|
@ -78,6 +78,7 @@ python-version = "3.11"
|
|||
```
|
||||
|
||||
```py
|
||||
import enum
|
||||
from typing import Literal, final
|
||||
|
||||
reveal_type(bool(1)) # revealed: Literal[True]
|
||||
|
|
@ -129,13 +130,20 @@ class FinalClassWithNoLenOrBool: ...
|
|||
|
||||
reveal_type(bool(FinalClassWithNoLenOrBool())) # revealed: Literal[True]
|
||||
|
||||
def f(x: SingleElementTupleSubclass | FinalClassOverridingLenAndNotBool | FinalClassWithNoLenOrBool):
|
||||
class EnumWithMembers(enum.Enum):
|
||||
A = 1
|
||||
B = 2
|
||||
|
||||
reveal_type(bool(EnumWithMembers.A)) # revealed: Literal[True]
|
||||
|
||||
def f(x: SingleElementTupleSubclass | FinalClassOverridingLenAndNotBool | FinalClassWithNoLenOrBool | Literal[EnumWithMembers.A]):
|
||||
reveal_type(bool(x)) # revealed: Literal[True]
|
||||
```
|
||||
|
||||
## Falsy values
|
||||
|
||||
```py
|
||||
import enum
|
||||
from typing import final, Literal
|
||||
|
||||
reveal_type(bool(0)) # revealed: Literal[False]
|
||||
|
|
@ -156,13 +164,23 @@ class FinalClassOverridingLenAndNotBool:
|
|||
|
||||
reveal_type(bool(FinalClassOverridingLenAndNotBool())) # revealed: Literal[False]
|
||||
|
||||
def f(x: EmptyTupleSubclass | FinalClassOverridingLenAndNotBool):
|
||||
class EnumWithMembersOverridingBool(enum.Enum):
|
||||
A = 1
|
||||
B = 2
|
||||
|
||||
def __bool__(self) -> Literal[False]:
|
||||
return False
|
||||
|
||||
reveal_type(bool(EnumWithMembersOverridingBool.A)) # revealed: Literal[False]
|
||||
|
||||
def f(x: EmptyTupleSubclass | FinalClassOverridingLenAndNotBool | Literal[EnumWithMembersOverridingBool.A]):
|
||||
reveal_type(bool(x)) # revealed: Literal[False]
|
||||
```
|
||||
|
||||
## Ambiguous values
|
||||
|
||||
```py
|
||||
import enum
|
||||
from typing import Literal
|
||||
|
||||
reveal_type(bool([])) # revealed: bool
|
||||
|
|
@ -182,6 +200,15 @@ class NonFinalOverridingLenAndNotBool:
|
|||
# because a subclass might override `__bool__`,
|
||||
# and `__bool__` takes precedence over `__len__`
|
||||
reveal_type(bool(NonFinalOverridingLenAndNotBool())) # revealed: bool
|
||||
|
||||
class EnumWithMembersOverridingBool(enum.Enum):
|
||||
A = 1
|
||||
B = 2
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return False
|
||||
|
||||
reveal_type(bool(EnumWithMembersOverridingBool.A)) # revealed: bool
|
||||
```
|
||||
|
||||
## `__bool__` returning `NoReturn`
|
||||
|
|
|
|||
|
|
@ -183,13 +183,11 @@ class CustomLenEnum(Enum):
|
|||
def __len__(self):
|
||||
return 0
|
||||
|
||||
# TODO: these could be `Literal[True]`
|
||||
reveal_type(bool(NormalEnum.NO)) # revealed: bool
|
||||
reveal_type(bool(NormalEnum.YES)) # revealed: bool
|
||||
reveal_type(bool(NormalEnum.NO)) # revealed: Literal[True]
|
||||
reveal_type(bool(NormalEnum.YES)) # revealed: Literal[True]
|
||||
|
||||
# TODO: these could be `Literal[False]`
|
||||
reveal_type(bool(FalsyEnum.NO)) # revealed: bool
|
||||
reveal_type(bool(FalsyEnum.YES)) # revealed: bool
|
||||
reveal_type(bool(FalsyEnum.NO)) # revealed: Literal[False]
|
||||
reveal_type(bool(FalsyEnum.YES)) # revealed: Literal[False]
|
||||
|
||||
# All of the following must be `bool`:
|
||||
|
||||
|
|
|
|||
|
|
@ -4692,10 +4692,10 @@ impl<'db> Type<'db> {
|
|||
Truthiness::Ambiguous
|
||||
}
|
||||
|
||||
Type::EnumLiteral(_) => {
|
||||
// We currently make no attempt to infer the precise truthiness, but it's not impossible to do so.
|
||||
// Note that custom `__bool__` or `__len__` methods on the class or superclasses affect the outcome.
|
||||
Truthiness::Ambiguous
|
||||
Type::EnumLiteral(enum_type) => {
|
||||
enum_type
|
||||
.enum_class_instance(db)
|
||||
.try_bool_impl(db, allow_short_circuit, visitor)?
|
||||
}
|
||||
|
||||
Type::IntLiteral(num) => Truthiness::from(*num != 0),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue