Skip to content

Commit b0f07a1

Browse files
committed
further improve encapsulation of InstanceType
1 parent 02e6f32 commit b0f07a1

File tree

4 files changed

+51
-44
lines changed

4 files changed

+51
-44
lines changed

crates/red_knot_python_semantic/src/types.rs

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,8 @@ pub enum Type<'db> {
465465
GenericAlias(GenericAlias<'db>),
466466
/// The set of all class objects that are subclasses of the given class (C), spelled `type[C]`.
467467
SubclassOf(SubclassOfType<'db>),
468-
/// The set of Python objects with the given class in their __class__'s method resolution order
468+
/// The set of Python objects with the given class in their __class__'s method resolution order.
469+
/// Construct this variant using the `Type::instance` constructor function.
469470
Instance(InstanceType<'db>),
470471
/// A single Python object that requires special treatment in the type system
471472
KnownInstance(KnownInstanceType<'db>),
@@ -695,10 +696,6 @@ impl<'db> Type<'db> {
695696
)
696697
}
697698

698-
pub const fn is_instance(&self) -> bool {
699-
matches!(self, Type::Instance(..))
700-
}
701-
702699
pub const fn is_property_instance(&self) -> bool {
703700
matches!(self, Type::PropertyInstance(..))
704701
}
@@ -799,13 +796,6 @@ impl<'db> Type<'db> {
799796
.expect("Expected a Type::IntLiteral variant")
800797
}
801798

802-
pub const fn into_instance(self) -> Option<InstanceType<'db>> {
803-
match self {
804-
Type::Instance(instance_type) => Some(instance_type),
805-
_ => None,
806-
}
807-
}
808-
809799
pub const fn into_known_instance(self) -> Option<KnownInstanceType<'db>> {
810800
match self {
811801
Type::KnownInstance(known_instance) => Some(known_instance),
@@ -1901,12 +1891,7 @@ impl<'db> Type<'db> {
19011891
other.is_disjoint_from(db, KnownClass::ModuleType.to_instance(db))
19021892
}
19031893

1904-
(Type::Instance(left_instance), Type::Instance(right_instance)) => {
1905-
let left_class = left_instance.class();
1906-
let right_class = right_instance.class();
1907-
(left_class.is_final(db) && !left_class.is_subclass_of(db, right_class))
1908-
|| (right_class.is_final(db) && !right_class.is_subclass_of(db, left_class))
1909-
}
1894+
(Type::Instance(left), Type::Instance(right)) => left.is_disjoint_from(db, right),
19101895

19111896
(Type::Tuple(tuple), Type::Tuple(other_tuple)) => {
19121897
let self_elements = tuple.elements(db);
@@ -2085,10 +2070,7 @@ impl<'db> Type<'db> {
20852070
false
20862071
}
20872072
Type::DataclassDecorator(_) | Type::DataclassTransformer(_) => false,
2088-
Type::Instance(instance) => instance
2089-
.class()
2090-
.known(db)
2091-
.is_some_and(KnownClass::is_singleton),
2073+
Type::Instance(instance) => instance.is_singleton(db),
20922074
Type::PropertyInstance(_) => false,
20932075
Type::Tuple(..) => {
20942076
// The empty tuple is a singleton on CPython and PyPy, but not on other Python
@@ -2160,10 +2142,7 @@ impl<'db> Type<'db> {
21602142
.iter()
21612143
.all(|elem| elem.is_single_valued(db)),
21622144

2163-
Type::Instance(instance) => instance
2164-
.class()
2165-
.known(db)
2166-
.is_some_and(KnownClass::is_single_valued),
2145+
Type::Instance(instance) => instance.is_single_valued(db),
21672146

21682147
Type::BoundSuper(_) => {
21692148
// At runtime two super instances never compare equal, even if their arguments are identical.
@@ -4633,8 +4612,8 @@ impl<'db> Type<'db> {
46334612
pub fn to_meta_type(&self, db: &'db dyn Db) -> Type<'db> {
46344613
match self {
46354614
Type::Never => Type::Never,
4636-
Type::Instance(instance) => SubclassOfType::from(db, instance.class()),
4637-
Type::KnownInstance(known_instance) => known_instance.class().to_class_literal(db),
4615+
Type::Instance(instance) => instance.to_meta_type(db),
4616+
Type::KnownInstance(known_instance) => known_instance.to_meta_type(db),
46384617
Type::PropertyInstance(_) => KnownClass::Property.to_class_literal(db),
46394618
Type::Union(union) => union.map(db, |ty| ty.to_meta_type(db)),
46404619
Type::BooleanLiteral(_) => KnownClass::Bool.to_class_literal(db),

crates/red_knot_python_semantic/src/types/class.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use crate::semantic_index::definition::Definition;
1010
use crate::semantic_index::DeclarationWithConstraint;
1111
use crate::types::generics::{GenericContext, Specialization};
1212
use crate::types::signatures::{Parameter, Parameters};
13-
use crate::types::{CallableType, DataclassParams, DataclassTransformerParams, KnownInstanceType, Signature};
13+
use crate::types::{
14+
CallableType, DataclassParams, DataclassTransformerParams, KnownInstanceType, Signature,
15+
};
1416
use crate::{
1517
module_resolver::file_to_module,
1618
semantic_index::{

crates/red_knot_python_semantic/src/types/instance.rs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
//! Instance types: both nominal and structural.
22
3-
use super::{ClassType, Type};
3+
use super::{ClassType, KnownClass, SubclassOfType, Type};
44
use crate::Db;
55

6+
impl<'db> Type<'db> {
7+
pub(crate) const fn instance(class: ClassType<'db>) -> Self {
8+
Self::Instance(InstanceType { class })
9+
}
10+
11+
pub(crate) const fn into_instance(self) -> Option<InstanceType<'db>> {
12+
match self {
13+
Type::Instance(instance_type) => Some(instance_type),
14+
_ => None,
15+
}
16+
}
17+
}
18+
619
/// A type representing the set of runtime objects which are instances of a certain nominal class.
720
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
821
pub struct InstanceType<'db> {
@@ -16,36 +29,45 @@ impl<'db> InstanceType<'db> {
1629
self.class
1730
}
1831

19-
pub(super) fn is_subtype_of(self, db: &'db dyn Db, other: InstanceType<'db>) -> bool {
32+
pub(super) fn is_subtype_of(self, db: &'db dyn Db, other: Self) -> bool {
2033
// N.B. The subclass relation is fully static
2134
self.class.is_subclass_of(db, other.class)
2235
}
2336

24-
pub(super) fn is_equivalent_to(self, db: &'db dyn Db, other: InstanceType<'db>) -> bool {
37+
pub(super) fn is_equivalent_to(self, db: &'db dyn Db, other: Self) -> bool {
2538
self.class.is_equivalent_to(db, other.class)
2639
}
2740

28-
pub(super) fn is_assignable_to(self, db: &'db dyn Db, other: InstanceType<'db>) -> bool {
41+
pub(super) fn is_assignable_to(self, db: &'db dyn Db, other: Self) -> bool {
2942
self.class.is_assignable_to(db, other.class)
3043
}
3144

32-
pub(super) fn is_gradual_equivalent_to(
33-
self,
34-
db: &'db dyn Db,
35-
other: InstanceType<'db>,
36-
) -> bool {
45+
pub(super) fn is_disjoint_from(self, db: &'db dyn Db, other: Self) -> bool {
46+
(self.class.is_final(db) && !self.class.is_subclass_of(db, other.class))
47+
|| (other.class.is_final(db) && !other.class.is_subclass_of(db, self.class))
48+
}
49+
50+
pub(super) fn is_gradual_equivalent_to(self, db: &'db dyn Db, other: Self) -> bool {
3751
self.class.is_gradual_equivalent_to(db, other.class)
3852
}
53+
54+
pub(super) fn is_singleton(self, db: &'db dyn Db) -> bool {
55+
self.class.known(db).is_some_and(KnownClass::is_singleton)
56+
}
57+
58+
pub(super) fn is_single_valued(self, db: &'db dyn Db) -> bool {
59+
self.class
60+
.known(db)
61+
.is_some_and(KnownClass::is_single_valued)
62+
}
63+
64+
pub(super) fn to_meta_type(self, db: &'db dyn Db) -> Type<'db> {
65+
SubclassOfType::from(db, self.class)
66+
}
3967
}
4068

4169
impl<'db> From<InstanceType<'db>> for Type<'db> {
4270
fn from(value: InstanceType<'db>) -> Self {
4371
Self::Instance(value)
4472
}
4573
}
46-
47-
impl<'db> Type<'db> {
48-
pub const fn instance(class: ClassType<'db>) -> Self {
49-
Self::Instance(InstanceType { class })
50-
}
51-
}

crates/red_knot_python_semantic/src/types/known_instance.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,4 +365,8 @@ impl<'db> KnownInstanceType<'db> {
365365
| Self::CallableTypeOf => module.is_knot_extensions(),
366366
}
367367
}
368+
369+
pub(super) fn to_meta_type(self, db: &'db dyn Db) -> Type<'db> {
370+
self.class().to_class_literal(db)
371+
}
368372
}

0 commit comments

Comments
 (0)