Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,29 @@ static_assert(is_disjoint_from(Callable[[], None], Literal[b""]))
static_assert(is_disjoint_from(Callable[[], None], Literal[1]))
static_assert(is_disjoint_from(Callable[[], None], Literal[True]))
```

## Bound Super

If both `super` are fully static, they are disjoint when at least one of their parameters differs.
On the other hand, if either `super` is not fully static, they should never be considered disjoint.

```py
from ty_extensions import TypeOf, is_disjoint_from, static_assert

def f(x):
static_assert(is_disjoint_from(TypeOf[super(int, int())], TypeOf[super(str, str())]))
static_assert(is_disjoint_from(TypeOf[super(int, int())], TypeOf[super(int, bool())]))
static_assert(not is_disjoint_from(TypeOf[super(int, int)], TypeOf[super(int, int)]))
static_assert(
not is_disjoint_from(
TypeOf[super(int, int())],
TypeOf[super(int, int())],
)
)

# includes gradual types
static_assert(not is_disjoint_from(TypeOf[super(x, x)], TypeOf[super(x, x)]))
static_assert(not is_disjoint_from(TypeOf[super(x, int())], TypeOf[super(x, str())]))
static_assert(not is_disjoint_from(TypeOf[super(int, x)], TypeOf[super(str, x)]))
static_assert(not is_disjoint_from(TypeOf[super(int, x)], TypeOf[super(x, int())]))
```
21 changes: 17 additions & 4 deletions crates/ty_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2087,10 +2087,23 @@ impl<'db> Type<'db> {
.is_disjoint_from(db, other)
}

(Type::BoundSuper(_), Type::BoundSuper(_)) => !self.is_equivalent_to(db, other),
(Type::BoundSuper(_), other) | (other, Type::BoundSuper(_)) => KnownClass::Super
.to_instance(db)
.is_disjoint_from(db, other),
(Type::BoundSuper(_), Type::BoundSuper(_)) => {
if self.is_fully_static(db) && other.is_fully_static(db) {
!self.is_equivalent_to(db, other)
} else {
false
}
}
(bound_super @ Type::BoundSuper(_), other)
| (other, bound_super @ Type::BoundSuper(_)) => {
if bound_super.is_fully_static(db) {
KnownClass::Super
.to_instance(db)
.is_disjoint_from(db, other)
} else {
false
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::db::tests::TestDb;
use crate::symbol::{builtins_symbol, known_module_symbol};
use crate::types::{
BoundMethodType, CallableType, IntersectionBuilder, KnownClass, KnownInstanceType, Parameter,
Parameters, Signature, SubclassOfType, TupleType, Type, UnionType,
BoundMethodType, BoundSuperType, CallableType, IntersectionBuilder, KnownClass,
KnownInstanceType, Parameter, Parameters, Signature, SubclassOfType, TupleType, Type,
UnionType,
};
use crate::{Db, KnownModule};
use hashbrown::HashSet;
Expand Down Expand Up @@ -53,6 +54,10 @@ pub(crate) enum Ty {
params: CallableParams,
returns: Option<Box<Ty>>,
},
BoundSuper {
pivot: SuperParamKind,
owner: SuperParamKind,
},
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -117,6 +122,29 @@ fn create_bound_method<'db>(
))
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum SuperParamKind {
BuiltinClass(&'static str),
BuiltinInstance(&'static str),
Unknown,
}

impl SuperParamKind {
fn into_type(self, db: &TestDb) -> Type<'_> {
match self {
SuperParamKind::BuiltinClass(class_name) => {
builtins_symbol(db, class_name).symbol.expect_type()
}
SuperParamKind::BuiltinInstance(class_name) => builtins_symbol(db, class_name)
.symbol
.expect_type()
.to_instance(db)
.unwrap(),
SuperParamKind::Unknown => Type::unknown(),
}
}
}

impl Ty {
pub(crate) fn into_type(self, db: &TestDb) -> Type<'_> {
match self {
Expand Down Expand Up @@ -195,6 +223,10 @@ impl Ty {
returns.map(|ty| ty.into_type(db)),
),
)),
Ty::BoundSuper { pivot, owner } => {
BoundSuperType::build(db, pivot.into_type(db), owner.into_type(db))
.expect("Failed to build a BoundSuperType")
}
}
}
}
Expand Down Expand Up @@ -253,6 +285,18 @@ fn arbitrary_core_type(g: &mut Gen) -> Ty {
class: "int",
method: "bit_length",
},
Ty::BoundSuper {
pivot: SuperParamKind::BuiltinClass("int"),
owner: SuperParamKind::BuiltinInstance("bool"),
},
Ty::BoundSuper {
pivot: SuperParamKind::BuiltinClass("int"),
owner: SuperParamKind::BuiltinClass("bool"),
},
Ty::BoundSuper {
pivot: SuperParamKind::Unknown,
owner: SuperParamKind::Unknown,
},
])
.unwrap()
.clone()
Expand Down
Loading