Skip to content

Commit cdb3a78

Browse files
committed
Future-proof Type::is_disjoint_from()
1 parent deac0e4 commit cdb3a78

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
@@ -1222,10 +1222,9 @@ impl<'db> Type<'db> {
12221222
| (
12231223
Type::Instance(InstanceType { class: class_other }),
12241224
Type::Instance(InstanceType { class: class_none }),
1225-
) if class_none.is_known(db, KnownClass::NoneType) => !matches!(
1226-
class_other.known(db),
1227-
Some(KnownClass::NoneType | KnownClass::Object)
1228-
),
1225+
) if class_none.is_known(db, KnownClass::NoneType) => {
1226+
!class_none.is_subclass_of(db, class_other)
1227+
}
12291228

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

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

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

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

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

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

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

12761287
(
12771288
Type::ClassLiteral(ClassLiteralType { class: class_a }),
@@ -1283,15 +1294,17 @@ impl<'db> Type<'db> {
12831294
) => !class_a.is_instance_of(db, class_b),
12841295

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

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

0 commit comments

Comments
 (0)