mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:24:57 +00:00
[ty] Remove incorrect type narrowing for if type(x) is C[int]
(#19926)
This commit is contained in:
parent
f344dda82c
commit
9ced219ffc
2 changed files with 52 additions and 6 deletions
|
@ -70,6 +70,56 @@ def _(x: A | B, y: A | C):
|
||||||
reveal_type(y) # revealed: A
|
reveal_type(y) # revealed: A
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## No narrowing for `type(x) is C[int]`
|
||||||
|
|
||||||
|
At runtime, `type(x)` will never return a generic alias object (only ever a class-literal object),
|
||||||
|
so no narrowing can occur if `type(x)` is compared with a generic alias object.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
|
```py
|
||||||
|
class A[T]: ...
|
||||||
|
class B: ...
|
||||||
|
|
||||||
|
def f(x: A[int] | B):
|
||||||
|
if type(x) is A[int]:
|
||||||
|
# this branch is actually unreachable -- we *could* reveal `Never` here!
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
else:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
|
||||||
|
if type(x) is A:
|
||||||
|
# TODO: this should be `A[int]`, but `A[int] | B` would be better than `Never`
|
||||||
|
reveal_type(x) # revealed: Never
|
||||||
|
else:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
|
||||||
|
if type(x) is B:
|
||||||
|
reveal_type(x) # revealed: B
|
||||||
|
else:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
|
||||||
|
if type(x) is not A[int]:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
else:
|
||||||
|
# this branch is actually unreachable -- we *could* reveal `Never` here!
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
|
||||||
|
if type(x) is not A:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
else:
|
||||||
|
# TODO: this should be `A[int]`, but `A[int] | B` would be better than `Never`
|
||||||
|
reveal_type(x) # revealed: Never
|
||||||
|
|
||||||
|
if type(x) is not B:
|
||||||
|
reveal_type(x) # revealed: A[int] | B
|
||||||
|
else:
|
||||||
|
reveal_type(x) # revealed: B
|
||||||
|
```
|
||||||
|
|
||||||
## `type(x) == C`, `type(x) != C`
|
## `type(x) == C`, `type(x) != C`
|
||||||
|
|
||||||
No narrowing can occur for equality comparisons, since there might be a custom `__eq__`
|
No narrowing can occur for equality comparisons, since there might be a custom `__eq__`
|
||||||
|
|
|
@ -756,12 +756,8 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||||
node_index: _,
|
node_index: _,
|
||||||
},
|
},
|
||||||
}) if keywords.is_empty() => {
|
}) if keywords.is_empty() => {
|
||||||
let rhs_class = match rhs_ty {
|
let Type::ClassLiteral(rhs_class) = rhs_ty else {
|
||||||
Type::ClassLiteral(class) => class,
|
|
||||||
Type::GenericAlias(alias) => alias.origin(self.db),
|
|
||||||
_ => {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = match &**args {
|
let target = match &**args {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue