Skip to content

Commit cd5b3fb

Browse files
committed
wip: new class types
1 parent 2380ade commit cd5b3fb

File tree

12 files changed

+209
-117
lines changed

12 files changed

+209
-117
lines changed

crates/red_knot_python_semantic/src/types.rs

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ use crate::types::mro::{Mro, MroError, MroIterator};
4141
pub(crate) use crate::types::narrow::infer_narrowing_constraint;
4242
use crate::types::signatures::{Parameter, ParameterForm, ParameterKind, Parameters};
4343
use crate::{Db, FxOrderSet, Module, Program};
44-
pub(crate) use class::{Class, ClassLiteralType, InstanceType, KnownClass, KnownInstanceType};
44+
pub(crate) use class::{
45+
Class, ClassLiteralType, ClassType, GenericAlias, GenericClass, InstanceType, KnownClass,
46+
KnownInstanceType, NonGenericClass,
47+
};
4548

4649
mod builder;
4750
mod call;
@@ -327,7 +330,7 @@ impl<'db> Type<'db> {
327330
}
328331

329332
pub const fn class_literal(class: Class<'db>) -> Self {
330-
Self::ClassLiteral(ClassLiteralType { class })
333+
Self::ClassLiteral(class)
331334
}
332335

333336
pub const fn into_class_literal(self) -> Option<ClassLiteralType<'db>> {
@@ -703,10 +706,7 @@ impl<'db> Type<'db> {
703706

704707
// `Literal[<class 'C'>]` is a subtype of `type[B]` if `C` is a subclass of `B`,
705708
// since `type[B]` describes all possible runtime subclasses of the class object `B`.
706-
(
707-
Type::ClassLiteral(ClassLiteralType { class }),
708-
Type::SubclassOf(target_subclass_ty),
709-
) => target_subclass_ty
709+
(Type::ClassLiteral(class), Type::SubclassOf(target_subclass_ty)) => target_subclass_ty
710710
.subclass_of()
711711
.into_class()
712712
.is_some_and(|target_class| class.is_subclass_of(db, target_class)),
@@ -719,7 +719,7 @@ impl<'db> Type<'db> {
719719
// `Literal[str]` is a subtype of `type` because the `str` class object is an instance of its metaclass `type`.
720720
// `Literal[abc.ABC]` is a subtype of `abc.ABCMeta` because the `abc.ABC` class object
721721
// is an instance of its metaclass `abc.ABCMeta`.
722-
(Type::ClassLiteral(ClassLiteralType { class }), _) => {
722+
(Type::ClassLiteral(class), _) => {
723723
class.metaclass_instance_type(db).is_subtype_of(db, target)
724724
}
725725

@@ -1106,17 +1106,13 @@ impl<'db> Type<'db> {
11061106
Type::Tuple(..),
11071107
) => true,
11081108

1109-
(
1110-
Type::SubclassOf(subclass_of_ty),
1111-
Type::ClassLiteral(ClassLiteralType { class: class_b }),
1112-
)
1113-
| (
1114-
Type::ClassLiteral(ClassLiteralType { class: class_b }),
1115-
Type::SubclassOf(subclass_of_ty),
1116-
) => match subclass_of_ty.subclass_of() {
1117-
ClassBase::Dynamic(_) => false,
1118-
ClassBase::Class(class_a) => !class_b.is_subclass_of(db, class_a),
1119-
},
1109+
(Type::SubclassOf(subclass_of_ty), Type::ClassLiteral(class_b))
1110+
| (Type::ClassLiteral(class_b), Type::SubclassOf(subclass_of_ty)) => {
1111+
match subclass_of_ty.subclass_of() {
1112+
ClassBase::Dynamic(_) => false,
1113+
ClassBase::Class(class_a) => !class_b.is_subclass_of(db, class_a),
1114+
}
1115+
}
11201116

11211117
(
11221118
Type::SubclassOf(_),
@@ -1229,12 +1225,10 @@ impl<'db> Type<'db> {
12291225
// A class-literal type `X` is always disjoint from an instance type `Y`,
12301226
// unless the type expressing "all instances of `Z`" is a subtype of of `Y`,
12311227
// where `Z` is `X`'s metaclass.
1232-
(Type::ClassLiteral(ClassLiteralType { class }), instance @ Type::Instance(_))
1233-
| (instance @ Type::Instance(_), Type::ClassLiteral(ClassLiteralType { class })) => {
1234-
!class
1235-
.metaclass_instance_type(db)
1236-
.is_subtype_of(db, instance)
1237-
}
1228+
(Type::ClassLiteral(class), instance @ Type::Instance(_))
1229+
| (instance @ Type::Instance(_), Type::ClassLiteral(class)) => !class
1230+
.metaclass_instance_type(db)
1231+
.is_subtype_of(db, instance),
12381232

12391233
(Type::FunctionLiteral(..), Type::Instance(InstanceType { class }))
12401234
| (Type::Instance(InstanceType { class }), Type::FunctionLiteral(..)) => {
@@ -1521,7 +1515,7 @@ impl<'db> Type<'db> {
15211515

15221516
Type::Dynamic(_) | Type::Never => Some(Symbol::bound(self).into()),
15231517

1524-
Type::ClassLiteral(class_literal @ ClassLiteralType { class }) => {
1518+
Type::ClassLiteral(class) => {
15251519
match (class.known(db), name) {
15261520
(Some(KnownClass::FunctionType), "__get__") => Some(
15271521
Symbol::bound(Type::Callable(CallableType::WrapperDescriptorDunderGet))
@@ -1551,7 +1545,7 @@ impl<'db> Type<'db> {
15511545
"__get__" | "__set__" | "__delete__",
15521546
) => Some(Symbol::Unbound.into()),
15531547

1554-
_ => Some(class_literal.class_member(db, name)),
1548+
_ => Some(class.class_member(db, name)),
15551549
}
15561550
}
15571551

@@ -2001,7 +1995,7 @@ impl<'db> Type<'db> {
20011995
))
20021996
.into(),
20031997

2004-
Type::ClassLiteral(ClassLiteralType { class })
1998+
Type::ClassLiteral(class)
20051999
if name == "__get__" && class.is_known(db, KnownClass::FunctionType) =>
20062000
{
20072001
Symbol::bound(Type::Callable(CallableType::WrapperDescriptorDunderGet)).into()
@@ -2211,7 +2205,7 @@ impl<'db> Type<'db> {
22112205
Type::FunctionLiteral(_) => Truthiness::AlwaysTrue,
22122206
Type::Callable(_) => Truthiness::AlwaysTrue,
22132207
Type::ModuleLiteral(_) => Truthiness::AlwaysTrue,
2214-
Type::ClassLiteral(ClassLiteralType { class }) => class
2208+
Type::ClassLiteral(class) => class
22152209
.metaclass_instance_type(db)
22162210
.try_bool_impl(db, allow_short_circuit)?,
22172211
Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() {
@@ -2580,7 +2574,7 @@ impl<'db> Type<'db> {
25802574
)),
25812575
},
25822576

2583-
Type::ClassLiteral(ClassLiteralType { class }) => match class.known(db) {
2577+
Type::ClassLiteral(class) => match class.known(db) {
25842578
Some(KnownClass::Bool) => {
25852579
// ```py
25862580
// class bool(int):
@@ -2924,7 +2918,7 @@ impl<'db> Type<'db> {
29242918
pub fn to_instance(&self, db: &'db dyn Db) -> Option<Type<'db>> {
29252919
match self {
29262920
Type::Dynamic(_) | Type::Never => Some(*self),
2927-
Type::ClassLiteral(ClassLiteralType { class }) => Some(Type::instance(*class)),
2921+
Type::ClassLiteral(class) => Some(Type::instance(*class)),
29282922
Type::SubclassOf(subclass_of_ty) => Some(subclass_of_ty.to_instance()),
29292923
Type::Union(union) => {
29302924
let mut builder = UnionBuilder::new(db);
@@ -2964,7 +2958,7 @@ impl<'db> Type<'db> {
29642958
match self {
29652959
// Special cases for `float` and `complex`
29662960
// https://typing.readthedocs.io/en/latest/spec/special-types.html#special-cases-for-float-and-complex
2967-
Type::ClassLiteral(ClassLiteralType { class }) => {
2961+
Type::ClassLiteral(class) => {
29682962
let ty = match class.known(db) {
29692963
Some(KnownClass::Complex) => UnionType::from_elements(
29702964
db,
@@ -3218,7 +3212,7 @@ impl<'db> Type<'db> {
32183212
Type::Callable(CallableType::General(_)) => KnownClass::Type.to_instance(db),
32193213
Type::ModuleLiteral(_) => KnownClass::ModuleType.to_class_literal(db),
32203214
Type::Tuple(_) => KnownClass::Tuple.to_class_literal(db),
3221-
Type::ClassLiteral(ClassLiteralType { class }) => class.metaclass(db),
3215+
Type::ClassLiteral(class) => class.metaclass(db),
32223216
Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() {
32233217
ClassBase::Dynamic(_) => *self,
32243218
ClassBase::Class(class) => SubclassOfType::from(

crates/red_knot_python_semantic/src/types/call/bind.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::types::diagnostic::{
1818
};
1919
use crate::types::signatures::{Parameter, ParameterForm};
2020
use crate::types::{
21-
todo_type, BoundMethodType, CallableType, ClassLiteralType, KnownClass, KnownFunction,
22-
KnownInstanceType, UnionType,
21+
todo_type, BoundMethodType, CallableType, KnownClass, KnownFunction, KnownInstanceType,
22+
UnionType,
2323
};
2424
use ruff_db::diagnostic::{OldSecondaryDiagnosticMessage, Span};
2525
use ruff_python_ast as ast;
@@ -280,7 +280,7 @@ impl<'db> Bindings<'db> {
280280

281281
[_, Some(Type::KnownInstance(KnownInstanceType::TypeAliasType(
282282
type_alias,
283-
))), Some(Type::ClassLiteral(ClassLiteralType { class }))]
283+
))), Some(Type::ClassLiteral(class))]
284284
if class.is_known(db, KnownClass::TypeAliasType)
285285
&& function.name(db) == "__name__" =>
286286
{
@@ -290,7 +290,7 @@ impl<'db> Bindings<'db> {
290290
));
291291
}
292292

293-
[_, Some(Type::KnownInstance(KnownInstanceType::TypeVar(typevar))), Some(Type::ClassLiteral(ClassLiteralType { class }))]
293+
[_, Some(Type::KnownInstance(KnownInstanceType::TypeVar(typevar))), Some(Type::ClassLiteral(class))]
294294
if class.is_known(db, KnownClass::TypeVar)
295295
&& function.name(db) == "__name__" =>
296296
{
@@ -449,7 +449,7 @@ impl<'db> Bindings<'db> {
449449
_ => {}
450450
},
451451

452-
Type::ClassLiteral(ClassLiteralType { class }) => match class.known(db) {
452+
Type::ClassLiteral(class) => match class.known(db) {
453453
Some(KnownClass::Bool) => match overload.parameter_types() {
454454
[Some(arg)] => overload.set_return_type(arg.bool(db).into_type(db)),
455455
[None] => overload.set_return_type(Type::BooleanLiteral(false)),

0 commit comments

Comments
 (0)