From 01a722547aa9d66ffc8749769b2c6786e1718395 Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 3 Dec 2024 09:50:33 +0100 Subject: [PATCH] [red-knot] `is_subtype_of` fix for `KnownInstance` types `KnownInstance::instance_fallback` may return instances of supertypes. For example, it returns an instance of `_SpecialForm` for `Literal`. This means it can't be used on the right-hand side of `is_subtype_of` relationships, because it might lead to false positives. I can lead to false negatives on the left hand side of `is_subtype_of`, but this is at least a known limitation. False negatives are fine for most applications, but false positives can lead to wrong results in intersection-simplification, for example. --- crates/red_knot_python_semantic/src/types.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 7e412936dbf7c..8fab2df3348b0 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -722,9 +722,6 @@ impl<'db> Type<'db> { (Type::KnownInstance(left), right) => { left.instance_fallback(db).is_subtype_of(db, right) } - (left, Type::KnownInstance(right)) => { - left.is_subtype_of(db, right.instance_fallback(db)) - } (Type::Instance(left), Type::Instance(right)) => left.is_instance_of(db, right.class), // TODO _ => false, @@ -3270,6 +3267,7 @@ pub(crate) mod tests { #[test_case(Ty::IntLiteral(1), Ty::Intersection{pos: vec![Ty::BuiltinInstance("int")], neg: vec![Ty::IntLiteral(1)]})] #[test_case(Ty::BuiltinClassLiteral("int"), Ty::BuiltinClassLiteral("object"))] #[test_case(Ty::BuiltinInstance("int"), Ty::BuiltinClassLiteral("int"))] + #[test_case(Ty::TypingInstance("_SpecialForm"), Ty::TypingLiteral)] fn is_not_subtype_of(from: Ty, to: Ty) { let db = setup_db(); assert!(!from.into_type(&db).is_subtype_of(&db, to.into_type(&db)));