Skip to content

Commit bee1e59

Browse files
committed
Future-proof Type::is_disjoint_from()
1 parent 0743838 commit bee1e59

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
@@ -1219,10 +1219,9 @@ impl<'db> Type<'db> {
12191219
| (
12201220
Type::Instance(InstanceType { class: class_other }),
12211221
Type::Instance(InstanceType { class: class_none }),
1222-
) if class_none.is_known(db, KnownClass::NoneType) => !matches!(
1223-
class_other.known(db),
1224-
Some(KnownClass::NoneType | KnownClass::Object)
1225-
),
1222+
) if class_none.is_known(db, KnownClass::NoneType) => {
1223+
!class_none.is_subclass_of(db, class_other)
1224+
}
12261225

12271226
(Type::Instance(InstanceType { class: class_none }), _)
12281227
| (_, Type::Instance(InstanceType { class: class_none }))
@@ -1232,43 +1231,55 @@ impl<'db> Type<'db> {
12321231
}
12331232

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

12411242
(Type::IntLiteral(..), Type::Instance(InstanceType { class }))
12421243
| (Type::Instance(InstanceType { class }), Type::IntLiteral(..)) => {
1243-
!matches!(class.known(db), Some(KnownClass::Int | KnownClass::Object))
1244+
// A `Type::IntLiteral()` must be an instance of exactly `int
1245+
// (it cannot be an instance of an `int` subclass)
1246+
!KnownClass::Int.is_subclass_of(db, class)
12441247
}
1248+
12451249
(Type::IntLiteral(..), _) | (_, Type::IntLiteral(..)) => true,
12461250

12471251
(Type::StringLiteral(..), Type::LiteralString)
12481252
| (Type::LiteralString, Type::StringLiteral(..)) => false,
1249-
(Type::StringLiteral(..), Type::Instance(InstanceType { class }))
1250-
| (Type::Instance(InstanceType { class }), Type::StringLiteral(..)) => {
1251-
!matches!(class.known(db), Some(KnownClass::Str | KnownClass::Object))
1253+
1254+
(
1255+
Type::StringLiteral(..) | Type::LiteralString,
1256+
Type::Instance(InstanceType { class }),
1257+
)
1258+
| (
1259+
Type::Instance(InstanceType { class }),
1260+
Type::StringLiteral(..) | Type::LiteralString,
1261+
) => {
1262+
// A `Type::StringLiteral()` or a `Type::LiteralString` must be an instance of exactly `str`
1263+
// (it cannot be an instance of a `str` subclass)
1264+
!KnownClass::Str.is_subclass_of(db, class)
12521265
}
12531266

12541267
(Type::LiteralString, Type::LiteralString) => false,
1255-
(Type::LiteralString, Type::Instance(InstanceType { class }))
1256-
| (Type::Instance(InstanceType { class }), Type::LiteralString) => {
1257-
!matches!(class.known(db), Some(KnownClass::Str | KnownClass::Object))
1258-
}
12591268
(Type::LiteralString, _) | (_, Type::LiteralString) => true,
12601269

12611270
(Type::BytesLiteral(..), Type::Instance(InstanceType { class }))
1262-
| (Type::Instance(InstanceType { class }), Type::BytesLiteral(..)) => !matches!(
1263-
class.known(db),
1264-
Some(KnownClass::Bytes | KnownClass::Object)
1265-
),
1271+
| (Type::Instance(InstanceType { class }), Type::BytesLiteral(..)) => {
1272+
// A `Type::BytesLiteral()` must be an instance of exactly `bytes`
1273+
// (it cannot be an instance of a `bytes` subclass)
1274+
!KnownClass::Bytes.is_subclass_of(db, class)
1275+
}
12661276

12671277
(Type::SliceLiteral(..), Type::Instance(InstanceType { class }))
1268-
| (Type::Instance(InstanceType { class }), Type::SliceLiteral(..)) => !matches!(
1269-
class.known(db),
1270-
Some(KnownClass::Slice | KnownClass::Object)
1271-
),
1278+
| (Type::Instance(InstanceType { class }), Type::SliceLiteral(..)) => {
1279+
// A `Type::SliceLiteral` must be an instance of exactly `slice`
1280+
// (it cannot be an instance of a `slice` subclass)
1281+
!KnownClass::Slice.is_subclass_of(db, class)
1282+
}
12721283

12731284
(
12741285
Type::ClassLiteral(ClassLiteralType { class: class_a }),
@@ -1280,15 +1291,17 @@ impl<'db> Type<'db> {
12801291
) => !class_a.is_instance_of(db, class_b),
12811292

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

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

0 commit comments

Comments
 (0)