-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
The is_assignable_to-is-reflexive property test, which makes sure that we can assign any type to itself, is currently failing with counter-examples like Any & T, where T is an arbitrary type (that doesn't let the intersection collapse).
The reason for this is that we can't rely on equivalence for assignability of gradual types anymore ever since #14758. We do have some special casing for gradual types like Any and Unknown, as well as for unions and tuples of these, but we do lack handling of intersections.
This is not completely trivial. We can patch this with some superficial handling like
--- a/crates/red_knot_python_semantic/src/types.rs
+++ b/crates/red_knot_python_semantic/src/types.rs
@@ -748,6 +748,14 @@ impl<'db> Type<'db> {
.elements(db)
.iter()
.any(|&elem_ty| ty.is_assignable_to(db, elem_ty)),
+ (Type::Intersection(intersection), ty) => intersection
+ .positive(db)
+ .iter()
+ .any(|&elem_ty| elem_ty.is_assignable_to(db, ty)),
+ (ty, Type::Intersection(intersection)) => intersection
+ .positive(db)
+ .iter()
+ .any(|&elem_ty| ty.is_assignable_to(db, elem_ty)),
(Type::Tuple(self_tuple), Type::Tuple(target_tuple)) => {
let self_elements = self_tuple.elements(db);
let target_elements = target_tuple.elements(db);which also works for things like T & ~Any, because we always add Any/Unknown as positive contributions to intersections.
But then quickcheck finds types like ~tuple[Any, T], for which the simple handling above breaks.