Skip to content

Commit a89c77b

Browse files
committed
Future-proof Type::is_disjoint_from()
1 parent c44a2e7 commit a89c77b

File tree

1 file changed

+46
-33
lines changed
  • crates/red_knot_python_semantic/src

1 file changed

+46
-33
lines changed

crates/red_knot_python_semantic/src/types.rs

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,10 +1221,9 @@ impl<'db> Type<'db> {
12211221
| (
12221222
Type::Instance(InstanceType { class: class_other }),
12231223
Type::Instance(InstanceType { class: class_none }),
1224-
) if class_none.is_known(db, KnownClass::NoneType) => !matches!(
1225-
class_other.known(db),
1226-
Some(KnownClass::NoneType | KnownClass::Object)
1227-
),
1224+
) if class_none.is_known(db, KnownClass::NoneType) => {
1225+
!class_none.is_subclass_of(db, class_other)
1226+
}
12281227

12291228
(Type::Instance(InstanceType { class: class_none }), _)
12301229
| (_, Type::Instance(InstanceType { class: class_none }))
@@ -1234,43 +1233,55 @@ impl<'db> Type<'db> {
12341233
}
12351234

12361235
(Type::BooleanLiteral(..), Type::Instance(InstanceType { class }))
1237-
| (Type::Instance(InstanceType { class }), Type::BooleanLiteral(..)) => !matches!(
1238-
class.known(db),
1239-
Some(KnownClass::Bool | KnownClass::Int | KnownClass::Object)
1240-
),
1236+
| (Type::Instance(InstanceType { class }), Type::BooleanLiteral(..)) => {
1237+
// A `Type::BooleanLiteral()` must be an instance of exactly `bool`
1238+
// (it cannot be an instance of a `bool` subclass)
1239+
!KnownClass::Bool.is_subclass_of(db, class)
1240+
}
1241+
12411242
(Type::BooleanLiteral(..), _) | (_, Type::BooleanLiteral(..)) => true,
12421243

12431244
(Type::IntLiteral(..), Type::Instance(InstanceType { class }))
12441245
| (Type::Instance(InstanceType { class }), Type::IntLiteral(..)) => {
1245-
!matches!(class.known(db), Some(KnownClass::Int | KnownClass::Object))
1246+
// A `Type::IntLiteral()` must be an instance of exactly `int
1247+
// (it cannot be an instance of an `int` subclass)
1248+
!KnownClass::Int.is_subclass_of(db, class)
12461249
}
1250+
12471251
(Type::IntLiteral(..), _) | (_, Type::IntLiteral(..)) => true,
12481252

12491253
(Type::StringLiteral(..), Type::LiteralString)
12501254
| (Type::LiteralString, Type::StringLiteral(..)) => false,
1251-
(Type::StringLiteral(..), Type::Instance(InstanceType { class }))
1252-
| (Type::Instance(InstanceType { class }), Type::StringLiteral(..)) => {
1253-
!matches!(class.known(db), Some(KnownClass::Str | KnownClass::Object))
1255+
1256+
(
1257+
Type::StringLiteral(..) | Type::LiteralString,
1258+
Type::Instance(InstanceType { class }),
1259+
)
1260+
| (
1261+
Type::Instance(InstanceType { class }),
1262+
Type::StringLiteral(..) | Type::LiteralString,
1263+
) => {
1264+
// A `Type::StringLiteral()` or a `Type::LiteralString` must be an instance of exactly `str`
1265+
// (it cannot be an instance of a `str` subclass)
1266+
!KnownClass::Str.is_subclass_of(db, class)
12541267
}
12551268

12561269
(Type::LiteralString, Type::LiteralString) => false,
1257-
(Type::LiteralString, Type::Instance(InstanceType { class }))
1258-
| (Type::Instance(InstanceType { class }), Type::LiteralString) => {
1259-
!matches!(class.known(db), Some(KnownClass::Str | KnownClass::Object))
1260-
}
12611270
(Type::LiteralString, _) | (_, Type::LiteralString) => true,
12621271

12631272
(Type::BytesLiteral(..), Type::Instance(InstanceType { class }))
1264-
| (Type::Instance(InstanceType { class }), Type::BytesLiteral(..)) => !matches!(
1265-
class.known(db),
1266-
Some(KnownClass::Bytes | KnownClass::Object)
1267-
),
1273+
| (Type::Instance(InstanceType { class }), Type::BytesLiteral(..)) => {
1274+
// A `Type::BytesLiteral()` must be an instance of exactly `bytes`
1275+
// (it cannot be an instance of a `bytes` subclass)
1276+
!KnownClass::Bytes.is_subclass_of(db, class)
1277+
}
12681278

12691279
(Type::SliceLiteral(..), Type::Instance(InstanceType { class }))
1270-
| (Type::Instance(InstanceType { class }), Type::SliceLiteral(..)) => !matches!(
1271-
class.known(db),
1272-
Some(KnownClass::Slice | KnownClass::Object)
1273-
),
1280+
| (Type::Instance(InstanceType { class }), Type::SliceLiteral(..)) => {
1281+
// A `Type::SliceLiteral` must be an instance of exactly `slice`
1282+
// (it cannot be an instance of a `slice` subclass)
1283+
!KnownClass::Slice.is_subclass_of(db, class)
1284+
}
12741285

12751286
(
12761287
Type::ClassLiteral(ClassLiteralType { class: class_a }),
@@ -1282,15 +1293,17 @@ impl<'db> Type<'db> {
12821293
) => !class_a.is_instance_of(db, class_b),
12831294

12841295
(Type::FunctionLiteral(..), Type::Instance(InstanceType { class }))
1285-
| (Type::Instance(InstanceType { class }), Type::FunctionLiteral(..)) => !matches!(
1286-
class.known(db),
1287-
Some(KnownClass::FunctionType | KnownClass::Object)
1288-
),
1289-
(Type::ModuleLiteral(..), Type::Instance(InstanceType { class }))
1290-
| (Type::Instance(InstanceType { class }), Type::ModuleLiteral(..)) => !matches!(
1291-
class.known(db),
1292-
Some(KnownClass::ModuleType | KnownClass::Object)
1293-
),
1296+
| (Type::Instance(InstanceType { class }), Type::FunctionLiteral(..)) => {
1297+
// A `Type::FunctionLiteral()` must be an instance of exactly `types.FunctionType`
1298+
// (it cannot be an instance of a `types.FunctionType` subclass)
1299+
!KnownClass::FunctionType.is_subclass_of(db, class)
1300+
}
1301+
1302+
(Type::ModuleLiteral(..), other @ Type::Instance(..))
1303+
| (other @ Type::Instance(..), Type::ModuleLiteral(..)) => {
1304+
// Modules *can* actually be instances of `ModuleType` subclasses
1305+
other.is_disjoint_from(db, KnownClass::ModuleType.to_instance(db))
1306+
}
12941307

12951308
(Type::Instance(..), Type::Instance(..)) => {
12961309
// TODO: once we have support for `final`, there might be some cases where

0 commit comments

Comments
 (0)