diff --git a/crates/ty_python_semantic/resources/mdtest/generics/legacy/functions.md b/crates/ty_python_semantic/resources/mdtest/generics/legacy/functions.md index 50a5be7058..34c4f04ead 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/legacy/functions.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/legacy/functions.md @@ -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 +``` diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/functions.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/functions.md index 1193e91ba5..dd75b2c56a 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/functions.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/functions.md @@ -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 +``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index a9111f3581..916f9471a0 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -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