Skip to content

Commit 0db080d

Browse files
committed
[red-knot] Fixup a few edge cases regarding type[Any]
1 parent 6e11086 commit 0db080d

File tree

1 file changed

+29
-15
lines changed
  • crates/red_knot_python_semantic/src

1 file changed

+29
-15
lines changed

crates/red_knot_python_semantic/src/types.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -654,14 +654,20 @@ impl<'db> Type<'db> {
654654
},
655655
)
656656
}
657-
(Type::ClassLiteral(self_class), Type::SubclassOf(target_class)) => {
658-
self_class.class.is_subclass_of_base(db, target_class.base)
659-
}
657+
(
658+
Type::ClassLiteral(ClassLiteralType { class: self_class }),
659+
Type::SubclassOf(SubclassOfType {
660+
base: ClassBase::Class(target_class),
661+
}),
662+
) => self_class.is_subclass_of(db, target_class),
660663
(
661664
Type::Instance(InstanceType { class: self_class }),
662-
Type::SubclassOf(target_class),
663-
) if self_class.is_known(db, KnownClass::Type) => {
664-
self_class.is_subclass_of_base(db, target_class.base)
665+
Type::SubclassOf(SubclassOfType {
666+
base: ClassBase::Class(target_class),
667+
}),
668+
) => {
669+
self_class.is_known(db, KnownClass::Type)
670+
&& target_class.is_known(db, KnownClass::Type)
665671
}
666672
(
667673
Type::SubclassOf(SubclassOfType {
@@ -928,10 +934,18 @@ impl<'db> Type<'db> {
928934
| Type::ClassLiteral(..)),
929935
) => left != right,
930936

931-
(Type::SubclassOf(type_class), Type::ClassLiteral(class_literal))
932-
| (Type::ClassLiteral(class_literal), Type::SubclassOf(type_class)) => {
933-
!class_literal.class.is_subclass_of_base(db, type_class.base)
934-
}
937+
(
938+
Type::SubclassOf(SubclassOfType {
939+
base: ClassBase::Class(class_a),
940+
}),
941+
Type::ClassLiteral(ClassLiteralType { class: class_b }),
942+
)
943+
| (
944+
Type::ClassLiteral(ClassLiteralType { class: class_b }),
945+
Type::SubclassOf(SubclassOfType {
946+
base: ClassBase::Class(class_a),
947+
}),
948+
) => !class_b.is_subclass_of(db, class_a),
935949
(Type::SubclassOf(_), Type::SubclassOf(_)) => false,
936950
(Type::SubclassOf(_), Type::Instance(_)) | (Type::Instance(_), Type::SubclassOf(_)) => {
937951
false
@@ -2593,11 +2607,7 @@ impl<'db> Class<'db> {
25932607
pub fn is_subclass_of(self, db: &'db dyn Db, other: Class) -> bool {
25942608
// `is_subclass_of` is checking the subtype relation, in which gradual types do not
25952609
// participate, so we should not return `True` if we find `Any/Unknown` in the MRO.
2596-
self.is_subclass_of_base(db, other)
2597-
}
2598-
2599-
fn is_subclass_of_base(self, db: &'db dyn Db, other: impl Into<ClassBase<'db>>) -> bool {
2600-
self.iter_mro(db).contains(&other.into())
2610+
self.iter_mro(db).contains(&ClassBase::Class(other))
26012611
}
26022612

26032613
/// Return the explicit `metaclass` of this class, if one is defined.
@@ -3146,6 +3156,7 @@ pub(crate) mod tests {
31463156
#[test_case(Ty::BuiltinInstance("type"), Ty::SubclassOfAny)]
31473157
#[test_case(Ty::BuiltinInstance("type"), Ty::SubclassOfBuiltinClass("object"))]
31483158
#[test_case(Ty::BuiltinInstance("type"), Ty::BuiltinInstance("type"))]
3159+
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::SubclassOfAny)]
31493160
fn is_assignable_to(from: Ty, to: Ty) {
31503161
let db = setup_db();
31513162
assert!(from.into_type(&db).is_assignable_to(&db, to.into_type(&db)));
@@ -3242,6 +3253,8 @@ pub(crate) mod tests {
32423253
#[test_case(Ty::BuiltinClassLiteral("int"), Ty::BuiltinClassLiteral("object"))]
32433254
#[test_case(Ty::BuiltinInstance("int"), Ty::BuiltinClassLiteral("int"))]
32443255
#[test_case(Ty::TypingInstance("_SpecialForm"), Ty::TypingLiteral)]
3256+
#[test_case(Ty::BuiltinInstance("type"), Ty::SubclassOfBuiltinClass("str"))]
3257+
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::SubclassOfAny)]
32453258
fn is_not_subtype_of(from: Ty, to: Ty) {
32463259
let db = setup_db();
32473260
assert!(!from.into_type(&db).is_subtype_of(&db, to.into_type(&db)));
@@ -3401,6 +3414,7 @@ pub(crate) mod tests {
34013414
#[test_case(Ty::Intersection{pos: vec![Ty::BuiltinInstance("int"), Ty::IntLiteral(2)], neg: vec![]}, Ty::IntLiteral(2))]
34023415
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Tuple(vec![Ty::IntLiteral(1), Ty::BuiltinInstance("int")]))]
34033416
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::BuiltinInstance("type"))]
3417+
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::SubclassOfAny)]
34043418
fn is_not_disjoint_from(a: Ty, b: Ty) {
34053419
let db = setup_db();
34063420
let a = a.into_type(&db);

0 commit comments

Comments
 (0)