mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 15:14:42 +00:00
[ty] ~T
should never be assignable to T
(#20606)
## Summary
Currently we do not emit an error on this code:
```py
from ty_extensions import Not
def f[T](x: T, y: Not[T]) -> T:
x = y
return x
```
But we should do! `~T` should never be assignable to `T`.
This fixes a small regression introduced in
14fe1228e7 (diff-8049ab5af787dba29daa389bbe2b691560c15461ef536f122b1beab112a4b48aR1443-R1446)
,
where a branch that previously returned `false` was replaced with a
branch that returns `C::always_satisfiable` -- the opposite of what it
used to be! The regression occurred because we didn't have any tests for
this -- so I added some tests in this PR that fail on `main`. I only
spotted the problem because I was going through the code of
`has_relation_to_impl` with a fine toothcomb for
https://github.com/astral-sh/ruff/pull/20602 😄
This commit is contained in:
parent
caf48f4bfc
commit
0639da2552
3 changed files with 26 additions and 1 deletions
|
@ -530,3 +530,17 @@ age, name = team.employees[0]
|
|||
reveal_type(age) # revealed: Age
|
||||
reveal_type(name) # revealed: Name
|
||||
```
|
||||
|
||||
## `~T` is never assignable to `T`
|
||||
|
||||
```py
|
||||
from typing import TypeVar
|
||||
from ty_extensions import Not
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
def f(x: T, y: Not[T]) -> T:
|
||||
x = y # error: [invalid-assignment]
|
||||
y = x # error: [invalid-assignment]
|
||||
return x
|
||||
```
|
||||
|
|
|
@ -543,3 +543,14 @@ def _(x: int):
|
|||
|
||||
reveal_type(C().implicit_self(x)) # revealed: tuple[C, int]
|
||||
```
|
||||
|
||||
## `~T` is never assignable to `T`
|
||||
|
||||
```py
|
||||
from ty_extensions import Not
|
||||
|
||||
def f[T](x: T, y: Not[T]) -> T:
|
||||
x = y # error: [invalid-assignment]
|
||||
y = x # error: [invalid-assignment]
|
||||
return x
|
||||
```
|
||||
|
|
|
@ -1567,7 +1567,7 @@ impl<'db> Type<'db> {
|
|||
(Type::Intersection(intersection), Type::NonInferableTypeVar(_))
|
||||
if intersection.negative(db).contains(&target) =>
|
||||
{
|
||||
ConstraintSet::from(true)
|
||||
ConstraintSet::from(false)
|
||||
}
|
||||
|
||||
// Two identical typevars must always solve to the same type, so they are always
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue