Rename Type::Instance to Type::NominalInstance and InstanceType to NominalInstanceType
This commit is contained in:
@@ -1114,7 +1114,7 @@ mod tests {
|
||||
fn assert_bound_string_symbol<'db>(db: &'db dyn Db, symbol: Symbol<'db>) {
|
||||
assert!(matches!(
|
||||
symbol,
|
||||
Symbol::Type(Type::Instance(_), Boundness::Bound)
|
||||
Symbol::Type(Type::NominalInstance(_), Boundness::Bound)
|
||||
));
|
||||
assert_eq!(symbol.expect_type(), KnownClass::Str.to_instance(db));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ pub(crate) use crate::types::narrow::infer_narrowing_constraint;
|
||||
use crate::types::signatures::{Parameter, ParameterForm, Parameters};
|
||||
use crate::{Db, FxOrderSet, Module, Program};
|
||||
pub(crate) use class::{ClassLiteral, ClassType, GenericAlias, KnownClass};
|
||||
pub(crate) use instance::InstanceType;
|
||||
pub(crate) use instance::NominalInstanceType;
|
||||
pub(crate) use known_instance::KnownInstanceType;
|
||||
|
||||
mod builder;
|
||||
@@ -475,7 +475,7 @@ pub enum Type<'db> {
|
||||
SubclassOf(SubclassOfType<'db>),
|
||||
/// The set of Python objects with the given class in their __class__'s method resolution order.
|
||||
/// Construct this variant using the `Type::instance` constructor function.
|
||||
Instance(InstanceType<'db>),
|
||||
NominalInstance(NominalInstanceType<'db>),
|
||||
/// A single Python object that requires special treatment in the type system
|
||||
KnownInstance(KnownInstanceType<'db>),
|
||||
/// An instance of `builtins.property`
|
||||
@@ -510,7 +510,7 @@ pub enum Type<'db> {
|
||||
TypeVar(TypeVarInstance<'db>),
|
||||
// A bound super object like `super()` or `super(A, A())`
|
||||
// This type doesn't handle an unbound super object like `super(A)`; for that we just use
|
||||
// a `Type::Instance` of `builtins.super`.
|
||||
// a `Type::NominalInstance` of `builtins.super`.
|
||||
BoundSuper(BoundSuperType<'db>),
|
||||
// TODO protocols, overloads, generics
|
||||
}
|
||||
@@ -583,7 +583,7 @@ impl<'db> Type<'db> {
|
||||
| Self::BooleanLiteral(_)
|
||||
| Self::BytesLiteral(_)
|
||||
| Self::FunctionLiteral(_)
|
||||
| Self::Instance(_)
|
||||
| Self::NominalInstance(_)
|
||||
| Self::ModuleLiteral(_)
|
||||
| Self::ClassLiteral(_)
|
||||
| Self::KnownInstance(_)
|
||||
@@ -888,7 +888,7 @@ impl<'db> Type<'db> {
|
||||
Type::Tuple(tuple) => Type::Tuple(tuple.normalized(db)),
|
||||
Type::Callable(callable) => Type::Callable(callable.normalized(db)),
|
||||
Type::LiteralString
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::PropertyInstance(_)
|
||||
| Type::AlwaysFalsy
|
||||
| Type::AlwaysTruthy
|
||||
@@ -980,7 +980,7 @@ impl<'db> Type<'db> {
|
||||
(_, Type::Never) => false,
|
||||
|
||||
// Everything is a subtype of `object`.
|
||||
(_, Type::Instance(instance)) if instance.class().is_object(db) => true,
|
||||
(_, Type::NominalInstance(instance)) if instance.class().is_object(db) => true,
|
||||
|
||||
// A fully static typevar is always a subtype of itself, and is never a subtype of any
|
||||
// other typevar, since there is no guarantee that they will be specialized to the same
|
||||
@@ -1232,7 +1232,7 @@ impl<'db> Type<'db> {
|
||||
metaclass_instance_type.is_subtype_of(db, target)
|
||||
}),
|
||||
|
||||
// For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::Instance(_SpecialForm)`,
|
||||
// For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::NominalInstance(_SpecialForm)`,
|
||||
// because `Type::KnownInstance(KnownInstanceType::Type)` is a set with exactly one runtime value in it
|
||||
// (the symbol `typing.Type`), and that symbol is known to be an instance of `typing._SpecialForm` at runtime.
|
||||
(Type::KnownInstance(left), right) => {
|
||||
@@ -1241,11 +1241,11 @@ impl<'db> Type<'db> {
|
||||
|
||||
// `bool` is a subtype of `int`, because `bool` subclasses `int`,
|
||||
// which means that all instances of `bool` are also instances of `int`
|
||||
(Type::Instance(self_instance), Type::Instance(target_instance)) => {
|
||||
(Type::NominalInstance(self_instance), Type::NominalInstance(target_instance)) => {
|
||||
self_instance.is_subtype_of(db, target_instance)
|
||||
}
|
||||
|
||||
(Type::Instance(_), Type::Callable(_)) => {
|
||||
(Type::NominalInstance(_), Type::Callable(_)) => {
|
||||
let call_symbol = self.member(db, "__call__").symbol;
|
||||
match call_symbol {
|
||||
Symbol::Type(Type::BoundMethod(call_function), _) => call_function
|
||||
@@ -1264,7 +1264,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
// Other than the special cases enumerated above, `Instance` types and typevars are
|
||||
// never subtypes of any other variants
|
||||
(Type::Instance(_) | Type::TypeVar(_), _) => false,
|
||||
(Type::NominalInstance(_) | Type::TypeVar(_), _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1286,7 +1286,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
// All types are assignable to `object`.
|
||||
// TODO this special case might be removable once the below cases are comprehensive
|
||||
(_, Type::Instance(instance)) if instance.class().is_object(db) => true,
|
||||
(_, Type::NominalInstance(instance)) if instance.class().is_object(db) => true,
|
||||
|
||||
// A typevar is always assignable to itself, and is never assignable to any other
|
||||
// typevar, since there is no guarantee that they will be specialized to the same
|
||||
@@ -1420,7 +1420,7 @@ impl<'db> Type<'db> {
|
||||
// subtypes of `type[object]` are `type[...]` types (or `Never`), and `type[Any]` can
|
||||
// materialize to any `type[...]` type (or to `type[Never]`, which is equivalent to
|
||||
// `Never`.)
|
||||
(Type::SubclassOf(subclass_of_ty), Type::Instance(_))
|
||||
(Type::SubclassOf(subclass_of_ty), Type::NominalInstance(_))
|
||||
if subclass_of_ty.is_dynamic()
|
||||
&& (KnownClass::Type
|
||||
.to_instance(db)
|
||||
@@ -1432,7 +1432,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
// Any type that is assignable to `type[object]` is also assignable to `type[Any]`,
|
||||
// because `type[Any]` can materialize to `type[object]`.
|
||||
(Type::Instance(_), Type::SubclassOf(subclass_of_ty))
|
||||
(Type::NominalInstance(_), Type::SubclassOf(subclass_of_ty))
|
||||
if subclass_of_ty.is_dynamic()
|
||||
&& self.is_assignable_to(db, KnownClass::Type.to_instance(db)) =>
|
||||
{
|
||||
@@ -1441,11 +1441,11 @@ impl<'db> Type<'db> {
|
||||
|
||||
// TODO: This is a workaround to avoid false positives (e.g. when checking function calls
|
||||
// with `SupportsIndex` parameters), which should be removed when we understand protocols.
|
||||
(lhs, Type::Instance(instance))
|
||||
(lhs, Type::NominalInstance(instance))
|
||||
if instance.class().is_known(db, KnownClass::SupportsIndex) =>
|
||||
{
|
||||
match lhs {
|
||||
Type::Instance(instance)
|
||||
Type::NominalInstance(instance)
|
||||
if matches!(
|
||||
instance.class().known(db),
|
||||
Some(KnownClass::Int | KnownClass::SupportsIndex)
|
||||
@@ -1459,7 +1459,9 @@ impl<'db> Type<'db> {
|
||||
}
|
||||
|
||||
// TODO: ditto for avoiding false positives when checking function calls with `Sized` parameters.
|
||||
(lhs, Type::Instance(instance)) if instance.class().is_known(db, KnownClass::Sized) => {
|
||||
(lhs, Type::NominalInstance(instance))
|
||||
if instance.class().is_known(db, KnownClass::Sized) =>
|
||||
{
|
||||
matches!(
|
||||
lhs.to_meta_type(db).member(db, "__len__"),
|
||||
SymbolAndQualifiers {
|
||||
@@ -1469,7 +1471,7 @@ impl<'db> Type<'db> {
|
||||
)
|
||||
}
|
||||
|
||||
(Type::Instance(self_instance), Type::Instance(target_instance)) => {
|
||||
(Type::NominalInstance(self_instance), Type::NominalInstance(target_instance)) => {
|
||||
self_instance.is_assignable_to(db, target_instance)
|
||||
}
|
||||
|
||||
@@ -1477,7 +1479,7 @@ impl<'db> Type<'db> {
|
||||
self_callable.is_assignable_to(db, target_callable)
|
||||
}
|
||||
|
||||
(Type::Instance(_), Type::Callable(_)) => {
|
||||
(Type::NominalInstance(_), Type::Callable(_)) => {
|
||||
let call_symbol = self.member(db, "__call__").symbol;
|
||||
match call_symbol {
|
||||
Symbol::Type(Type::BoundMethod(call_function), _) => call_function
|
||||
@@ -1517,7 +1519,9 @@ impl<'db> Type<'db> {
|
||||
}
|
||||
(Type::Tuple(left), Type::Tuple(right)) => left.is_equivalent_to(db, right),
|
||||
(Type::Callable(left), Type::Callable(right)) => left.is_equivalent_to(db, right),
|
||||
(Type::Instance(left), Type::Instance(right)) => left.is_equivalent_to(db, right),
|
||||
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
|
||||
left.is_equivalent_to(db, right)
|
||||
}
|
||||
_ => self == other && self.is_fully_static(db) && other.is_fully_static(db),
|
||||
}
|
||||
}
|
||||
@@ -1552,7 +1556,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
(Type::TypeVar(first), Type::TypeVar(second)) => first == second,
|
||||
|
||||
(Type::Instance(first), Type::Instance(second)) => {
|
||||
(Type::NominalInstance(first), Type::NominalInstance(second)) => {
|
||||
first.is_gradual_equivalent_to(db, second)
|
||||
}
|
||||
|
||||
@@ -1780,8 +1784,8 @@ impl<'db> Type<'db> {
|
||||
.is_disjoint_from(db, other),
|
||||
},
|
||||
|
||||
(Type::KnownInstance(known_instance), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::KnownInstance(known_instance)) => {
|
||||
(Type::KnownInstance(known_instance), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::KnownInstance(known_instance)) => {
|
||||
!known_instance.is_instance_of(db, instance.class())
|
||||
}
|
||||
|
||||
@@ -1790,8 +1794,8 @@ impl<'db> Type<'db> {
|
||||
known_instance_ty.is_disjoint_from(db, KnownClass::Tuple.to_instance(db))
|
||||
}
|
||||
|
||||
(Type::BooleanLiteral(..), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::BooleanLiteral(..)) => {
|
||||
(Type::BooleanLiteral(..), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::BooleanLiteral(..)) => {
|
||||
// A `Type::BooleanLiteral()` must be an instance of exactly `bool`
|
||||
// (it cannot be an instance of a `bool` subclass)
|
||||
!KnownClass::Bool.is_subclass_of(db, instance.class())
|
||||
@@ -1799,8 +1803,8 @@ impl<'db> Type<'db> {
|
||||
|
||||
(Type::BooleanLiteral(..), _) | (_, Type::BooleanLiteral(..)) => true,
|
||||
|
||||
(Type::IntLiteral(..), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::IntLiteral(..)) => {
|
||||
(Type::IntLiteral(..), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::IntLiteral(..)) => {
|
||||
// A `Type::IntLiteral()` must be an instance of exactly `int`
|
||||
// (it cannot be an instance of an `int` subclass)
|
||||
!KnownClass::Int.is_subclass_of(db, instance.class())
|
||||
@@ -1811,8 +1815,8 @@ impl<'db> Type<'db> {
|
||||
(Type::StringLiteral(..), Type::LiteralString)
|
||||
| (Type::LiteralString, Type::StringLiteral(..)) => false,
|
||||
|
||||
(Type::StringLiteral(..) | Type::LiteralString, Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::StringLiteral(..) | Type::LiteralString) => {
|
||||
(Type::StringLiteral(..) | Type::LiteralString, Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::StringLiteral(..) | Type::LiteralString) => {
|
||||
// A `Type::StringLiteral()` or a `Type::LiteralString` must be an instance of exactly `str`
|
||||
// (it cannot be an instance of a `str` subclass)
|
||||
!KnownClass::Str.is_subclass_of(db, instance.class())
|
||||
@@ -1821,15 +1825,15 @@ impl<'db> Type<'db> {
|
||||
(Type::LiteralString, Type::LiteralString) => false,
|
||||
(Type::LiteralString, _) | (_, Type::LiteralString) => true,
|
||||
|
||||
(Type::BytesLiteral(..), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::BytesLiteral(..)) => {
|
||||
(Type::BytesLiteral(..), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::BytesLiteral(..)) => {
|
||||
// A `Type::BytesLiteral()` must be an instance of exactly `bytes`
|
||||
// (it cannot be an instance of a `bytes` subclass)
|
||||
!KnownClass::Bytes.is_subclass_of(db, instance.class())
|
||||
}
|
||||
|
||||
(Type::SliceLiteral(..), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::SliceLiteral(..)) => {
|
||||
(Type::SliceLiteral(..), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::SliceLiteral(..)) => {
|
||||
// A `Type::SliceLiteral` must be an instance of exactly `slice`
|
||||
// (it cannot be an instance of a `slice` subclass)
|
||||
!KnownClass::Slice.is_subclass_of(db, instance.class())
|
||||
@@ -1838,17 +1842,19 @@ impl<'db> Type<'db> {
|
||||
// A class-literal type `X` is always disjoint from an instance type `Y`,
|
||||
// unless the type expressing "all instances of `Z`" is a subtype of of `Y`,
|
||||
// where `Z` is `X`'s metaclass.
|
||||
(Type::ClassLiteral(class), instance @ Type::Instance(_))
|
||||
| (instance @ Type::Instance(_), Type::ClassLiteral(class)) => !class
|
||||
.metaclass_instance_type(db)
|
||||
.is_subtype_of(db, instance),
|
||||
(Type::GenericAlias(alias), instance @ Type::Instance(_))
|
||||
| (instance @ Type::Instance(_), Type::GenericAlias(alias)) => !ClassType::from(alias)
|
||||
(Type::ClassLiteral(class), instance @ Type::NominalInstance(_))
|
||||
| (instance @ Type::NominalInstance(_), Type::ClassLiteral(class)) => !class
|
||||
.metaclass_instance_type(db)
|
||||
.is_subtype_of(db, instance),
|
||||
(Type::GenericAlias(alias), instance @ Type::NominalInstance(_))
|
||||
| (instance @ Type::NominalInstance(_), Type::GenericAlias(alias)) => {
|
||||
!ClassType::from(alias)
|
||||
.metaclass_instance_type(db)
|
||||
.is_subtype_of(db, instance)
|
||||
}
|
||||
|
||||
(Type::FunctionLiteral(..), Type::Instance(instance))
|
||||
| (Type::Instance(instance), Type::FunctionLiteral(..)) => {
|
||||
(Type::FunctionLiteral(..), Type::NominalInstance(instance))
|
||||
| (Type::NominalInstance(instance), Type::FunctionLiteral(..)) => {
|
||||
// A `Type::FunctionLiteral()` must be an instance of exactly `types.FunctionType`
|
||||
// (it cannot be an instance of a `types.FunctionType` subclass)
|
||||
!KnownClass::FunctionType.is_subclass_of(db, instance.class())
|
||||
@@ -1904,13 +1910,15 @@ impl<'db> Type<'db> {
|
||||
false
|
||||
}
|
||||
|
||||
(Type::ModuleLiteral(..), other @ Type::Instance(..))
|
||||
| (other @ Type::Instance(..), Type::ModuleLiteral(..)) => {
|
||||
(Type::ModuleLiteral(..), other @ Type::NominalInstance(..))
|
||||
| (other @ Type::NominalInstance(..), Type::ModuleLiteral(..)) => {
|
||||
// Modules *can* actually be instances of `ModuleType` subclasses
|
||||
other.is_disjoint_from(db, KnownClass::ModuleType.to_instance(db))
|
||||
}
|
||||
|
||||
(Type::Instance(left), Type::Instance(right)) => left.is_disjoint_from(db, right),
|
||||
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
|
||||
left.is_disjoint_from(db, right)
|
||||
}
|
||||
|
||||
(Type::Tuple(tuple), Type::Tuple(other_tuple)) => {
|
||||
let self_elements = tuple.elements(db);
|
||||
@@ -1922,8 +1930,8 @@ impl<'db> Type<'db> {
|
||||
.any(|(e1, e2)| e1.is_disjoint_from(db, *e2))
|
||||
}
|
||||
|
||||
(Type::Tuple(..), instance @ Type::Instance(_))
|
||||
| (instance @ Type::Instance(_), Type::Tuple(..)) => {
|
||||
(Type::Tuple(..), instance @ Type::NominalInstance(_))
|
||||
| (instance @ Type::NominalInstance(_), Type::Tuple(..)) => {
|
||||
// We cannot be sure if the tuple is disjoint from the instance because:
|
||||
// - 'other' might be the homogeneous arbitrary-length tuple type
|
||||
// tuple[T, ...] (which we don't have support for yet); if all of
|
||||
@@ -1983,7 +1991,7 @@ impl<'db> Type<'db> {
|
||||
!matches!(bound_super.pivot_class(db), ClassBase::Dynamic(_))
|
||||
&& !matches!(bound_super.owner(db), SuperOwnerKind::Dynamic(_))
|
||||
}
|
||||
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::Instance(_) => {
|
||||
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::NominalInstance(_) => {
|
||||
// TODO: Ideally, we would iterate over the MRO of the class, check if all
|
||||
// bases are fully static, and only return `true` if that is the case.
|
||||
//
|
||||
@@ -2089,7 +2097,7 @@ impl<'db> Type<'db> {
|
||||
false
|
||||
}
|
||||
Type::DataclassDecorator(_) | Type::DataclassTransformer(_) => false,
|
||||
Type::Instance(instance) => instance.is_singleton(db),
|
||||
Type::NominalInstance(instance) => instance.is_singleton(db),
|
||||
Type::PropertyInstance(_) => false,
|
||||
Type::Tuple(..) => {
|
||||
// The empty tuple is a singleton on CPython and PyPy, but not on other Python
|
||||
@@ -2161,7 +2169,7 @@ impl<'db> Type<'db> {
|
||||
.iter()
|
||||
.all(|elem| elem.is_single_valued(db)),
|
||||
|
||||
Type::Instance(instance) => instance.is_single_valued(db),
|
||||
Type::NominalInstance(instance) => instance.is_single_valued(db),
|
||||
|
||||
Type::BoundSuper(_) => {
|
||||
// At runtime two super instances never compare equal, even if their arguments are identical.
|
||||
@@ -2299,10 +2307,11 @@ impl<'db> Type<'db> {
|
||||
.to_class_literal(db)
|
||||
.find_name_in_mro_with_policy(db, name, policy),
|
||||
|
||||
// We eagerly normalize type[object], i.e. Type::SubclassOf(object) to `type`, i.e. Type::Instance(type).
|
||||
// So looking up a name in the MRO of `Type::Instance(type)` is equivalent to looking up the name in the
|
||||
// We eagerly normalize type[object], i.e. Type::SubclassOf(object) to `type`,
|
||||
// i.e. Type::NominalInstance(type). So looking up a name in the MRO of
|
||||
// `Type::NominalInstance(type)` is equivalent to looking up the name in the
|
||||
// MRO of the class `object`.
|
||||
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Type) => {
|
||||
Type::NominalInstance(instance) if instance.class().is_known(db, KnownClass::Type) => {
|
||||
KnownClass::Object
|
||||
.to_class_literal(db)
|
||||
.find_name_in_mro_with_policy(db, name, policy)
|
||||
@@ -2327,7 +2336,7 @@ impl<'db> Type<'db> {
|
||||
| Type::SliceLiteral(_)
|
||||
| Type::Tuple(_)
|
||||
| Type::TypeVar(_)
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::PropertyInstance(_) => None,
|
||||
}
|
||||
}
|
||||
@@ -2392,7 +2401,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
Type::Dynamic(_) | Type::Never => Symbol::bound(self).into(),
|
||||
|
||||
Type::Instance(instance) => instance.class().instance_member(db, name),
|
||||
Type::NominalInstance(instance) => instance.class().instance_member(db, name),
|
||||
|
||||
Type::FunctionLiteral(_) => KnownClass::FunctionType
|
||||
.to_instance(db)
|
||||
@@ -2833,7 +2842,7 @@ impl<'db> Type<'db> {
|
||||
.to_instance(db)
|
||||
.member_lookup_with_policy(db, name, policy),
|
||||
|
||||
Type::Instance(instance)
|
||||
Type::NominalInstance(instance)
|
||||
if matches!(name.as_str(), "major" | "minor")
|
||||
&& instance.class().is_known(db, KnownClass::VersionInfo) =>
|
||||
{
|
||||
@@ -2875,7 +2884,7 @@ impl<'db> Type<'db> {
|
||||
policy,
|
||||
),
|
||||
|
||||
Type::Instance(..)
|
||||
Type::NominalInstance(..)
|
||||
| Type::BooleanLiteral(..)
|
||||
| Type::IntLiteral(..)
|
||||
| Type::StringLiteral(..)
|
||||
@@ -3167,7 +3176,7 @@ impl<'db> Type<'db> {
|
||||
}
|
||||
},
|
||||
|
||||
Type::Instance(instance) => match instance.class().known(db) {
|
||||
Type::NominalInstance(instance) => match instance.class().known(db) {
|
||||
Some(known_class) => known_class.bool(),
|
||||
None => try_dunder_bool()?,
|
||||
},
|
||||
@@ -3911,7 +3920,7 @@ impl<'db> Type<'db> {
|
||||
SubclassOfInner::Class(class) => Type::from(class).signatures(db),
|
||||
},
|
||||
|
||||
Type::Instance(_) => {
|
||||
Type::NominalInstance(_) => {
|
||||
// Note that for objects that have a (possibly not callable!) `__call__` attribute,
|
||||
// we will get the signature of the `__call__` attribute, but will pass in the type
|
||||
// of the original object as the "callable type". That ensures that we get errors
|
||||
@@ -4361,7 +4370,7 @@ impl<'db> Type<'db> {
|
||||
| Type::WrapperDescriptor(_)
|
||||
| Type::DataclassDecorator(_)
|
||||
| Type::DataclassTransformer(_)
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::KnownInstance(_)
|
||||
| Type::PropertyInstance(_)
|
||||
| Type::ModuleLiteral(_)
|
||||
@@ -4381,7 +4390,7 @@ impl<'db> Type<'db> {
|
||||
///
|
||||
/// For example, the builtin `int` as a value expression is of type
|
||||
/// `Type::ClassLiteral(builtins.int)`, that is, it is the `int` class itself. As a type
|
||||
/// expression, it names the type `Type::Instance(builtins.int)`, that is, all objects whose
|
||||
/// expression, it names the type `Type::NominalInstance(builtins.int)`, that is, all objects whose
|
||||
/// `__class__` is `int`.
|
||||
pub fn in_type_expression(
|
||||
&self,
|
||||
@@ -4558,7 +4567,7 @@ impl<'db> Type<'db> {
|
||||
|
||||
Type::Dynamic(_) => Ok(*self),
|
||||
|
||||
Type::Instance(instance) => match instance.class().known(db) {
|
||||
Type::NominalInstance(instance) => match instance.class().known(db) {
|
||||
Some(KnownClass::TypeVar) => Ok(todo_type!(
|
||||
"Support for `typing.TypeVar` instances in type expressions"
|
||||
)),
|
||||
@@ -4634,7 +4643,7 @@ impl<'db> Type<'db> {
|
||||
pub fn to_meta_type(&self, db: &'db dyn Db) -> Type<'db> {
|
||||
match self {
|
||||
Type::Never => Type::Never,
|
||||
Type::Instance(instance) => instance.to_meta_type(db),
|
||||
Type::NominalInstance(instance) => instance.to_meta_type(db),
|
||||
Type::KnownInstance(known_instance) => known_instance.to_meta_type(db),
|
||||
Type::PropertyInstance(_) => KnownClass::Property.to_class_literal(db),
|
||||
Type::Union(union) => union.map(db, |ty| ty.to_meta_type(db)),
|
||||
@@ -4805,7 +4814,7 @@ impl<'db> Type<'db> {
|
||||
| Type::BoundSuper(_)
|
||||
// Instance contains a ClassType, which has already been specialized if needed, like
|
||||
// above with BoundMethod's self_instance.
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::KnownInstance(_) => self,
|
||||
}
|
||||
}
|
||||
@@ -4869,7 +4878,7 @@ impl<'db> Type<'db> {
|
||||
Some(TypeDefinition::Class(class_literal.definition(db)))
|
||||
}
|
||||
Self::GenericAlias(alias) => Some(TypeDefinition::Class(alias.definition(db))),
|
||||
Self::Instance(instance) => {
|
||||
Self::NominalInstance(instance) => {
|
||||
Some(TypeDefinition::Class(instance.class().definition(db)))
|
||||
}
|
||||
Self::KnownInstance(instance) => match instance {
|
||||
@@ -7457,7 +7466,7 @@ impl BoundSuperError<'_> {
|
||||
pub enum SuperOwnerKind<'db> {
|
||||
Dynamic(DynamicType),
|
||||
Class(ClassType<'db>),
|
||||
Instance(InstanceType<'db>),
|
||||
Instance(NominalInstanceType<'db>),
|
||||
}
|
||||
|
||||
impl<'db> SuperOwnerKind<'db> {
|
||||
@@ -7491,7 +7500,7 @@ impl<'db> SuperOwnerKind<'db> {
|
||||
Type::ClassLiteral(class_literal) => Some(SuperOwnerKind::Class(
|
||||
class_literal.apply_optional_specialization(db, None),
|
||||
)),
|
||||
Type::Instance(instance) => Some(SuperOwnerKind::Instance(instance)),
|
||||
Type::NominalInstance(instance) => Some(SuperOwnerKind::Instance(instance)),
|
||||
Type::BooleanLiteral(_) => {
|
||||
SuperOwnerKind::try_from_type(db, KnownClass::Bool.to_instance(db))
|
||||
}
|
||||
|
||||
@@ -611,7 +611,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
|
||||
Type::AlwaysFalsy if addition_is_bool_instance => {
|
||||
new_positive = Type::BooleanLiteral(false);
|
||||
}
|
||||
Type::Instance(instance)
|
||||
Type::NominalInstance(instance)
|
||||
if instance.class().is_known(db, KnownClass::Bool) =>
|
||||
{
|
||||
match new_positive {
|
||||
@@ -722,7 +722,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
|
||||
Type::Never => {
|
||||
// Adding ~Never to an intersection is a no-op.
|
||||
}
|
||||
Type::Instance(instance) if instance.class().is_object(db) => {
|
||||
Type::NominalInstance(instance) if instance.class().is_object(db) => {
|
||||
// Adding ~object to an intersection results in Never.
|
||||
*self = Self::default();
|
||||
self.positive.insert(Type::Never);
|
||||
|
||||
@@ -78,12 +78,14 @@ impl<'db> ClassBase<'db> {
|
||||
Self::Class(literal.default_specialization(db))
|
||||
}),
|
||||
Type::GenericAlias(generic) => Some(Self::Class(ClassType::Generic(generic))),
|
||||
Type::Instance(instance) if instance.class().is_known(db, KnownClass::GenericAlias) => {
|
||||
Type::NominalInstance(instance)
|
||||
if instance.class().is_known(db, KnownClass::GenericAlias) =>
|
||||
{
|
||||
Self::try_from_type(db, todo_type!("GenericAlias instance"))
|
||||
}
|
||||
Type::Union(_) => None, // TODO -- forces consideration of multiple possible MROs?
|
||||
Type::Intersection(_) => None, // TODO -- probably incorrect?
|
||||
Type::Instance(_) => None, // TODO -- handle `__mro_entries__`?
|
||||
Type::NominalInstance(_) => None, // TODO -- handle `__mro_entries__`?
|
||||
Type::PropertyInstance(_) => None,
|
||||
Type::Never
|
||||
| Type::BooleanLiteral(_)
|
||||
|
||||
@@ -73,12 +73,14 @@ impl Display for DisplayRepresentation<'_> {
|
||||
match self.ty {
|
||||
Type::Dynamic(dynamic) => dynamic.fmt(f),
|
||||
Type::Never => f.write_str("Never"),
|
||||
Type::Instance(instance) => match (instance.class(), instance.class().known(self.db)) {
|
||||
(_, Some(KnownClass::NoneType)) => f.write_str("None"),
|
||||
(_, Some(KnownClass::NoDefaultType)) => f.write_str("NoDefault"),
|
||||
(ClassType::NonGeneric(class), _) => f.write_str(class.name(self.db)),
|
||||
(ClassType::Generic(alias), _) => write!(f, "{}", alias.display(self.db)),
|
||||
},
|
||||
Type::NominalInstance(instance) => {
|
||||
match (instance.class(), instance.class().known(self.db)) {
|
||||
(_, Some(KnownClass::NoneType)) => f.write_str("None"),
|
||||
(_, Some(KnownClass::NoDefaultType)) => f.write_str("NoDefault"),
|
||||
(ClassType::NonGeneric(class), _) => f.write_str(class.name(self.db)),
|
||||
(ClassType::Generic(alias), _) => write!(f, "{}", alias.display(self.db)),
|
||||
}
|
||||
}
|
||||
Type::PropertyInstance(_) => f.write_str("property"),
|
||||
Type::ModuleLiteral(module) => {
|
||||
write!(f, "<module '{}'>", module.module(self.db).name())
|
||||
|
||||
@@ -1064,7 +1064,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
) -> bool {
|
||||
match left {
|
||||
Type::BooleanLiteral(_) | Type::IntLiteral(_) => {}
|
||||
Type::Instance(instance)
|
||||
Type::NominalInstance(instance)
|
||||
if matches!(
|
||||
instance.class().known(self.db()),
|
||||
Some(KnownClass::Float | KnownClass::Int | KnownClass::Bool)
|
||||
@@ -2515,7 +2515,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
}
|
||||
|
||||
// Super instances do not allow attribute assignment
|
||||
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Super) => {
|
||||
Type::NominalInstance(instance) if instance.class().is_known(db, KnownClass::Super) => {
|
||||
if emit_diagnostics {
|
||||
if let Some(builder) = self.context.report_lint(&INVALID_ASSIGNMENT, target) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
@@ -2540,7 +2540,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
|
||||
Type::Dynamic(..) | Type::Never => true,
|
||||
|
||||
Type::Instance(..)
|
||||
Type::NominalInstance(..)
|
||||
| Type::BooleanLiteral(..)
|
||||
| Type::IntLiteral(..)
|
||||
| Type::StringLiteral(..)
|
||||
@@ -3031,7 +3031,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
}
|
||||
|
||||
// Handle various singletons.
|
||||
if let Type::Instance(instance) = declared_ty.inner_type() {
|
||||
if let Type::NominalInstance(instance) = declared_ty.inner_type() {
|
||||
if instance
|
||||
.class()
|
||||
.is_known(self.db(), KnownClass::SpecialForm)
|
||||
@@ -5007,7 +5007,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
| Type::ClassLiteral(_)
|
||||
| Type::GenericAlias(_)
|
||||
| Type::SubclassOf(_)
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::KnownInstance(_)
|
||||
| Type::PropertyInstance(_)
|
||||
| Type::Union(_)
|
||||
@@ -5287,7 +5287,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
| Type::ClassLiteral(_)
|
||||
| Type::GenericAlias(_)
|
||||
| Type::SubclassOf(_)
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::KnownInstance(_)
|
||||
| Type::PropertyInstance(_)
|
||||
| Type::Intersection(_)
|
||||
@@ -5312,7 +5312,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
| Type::ClassLiteral(_)
|
||||
| Type::GenericAlias(_)
|
||||
| Type::SubclassOf(_)
|
||||
| Type::Instance(_)
|
||||
| Type::NominalInstance(_)
|
||||
| Type::KnownInstance(_)
|
||||
| Type::PropertyInstance(_)
|
||||
| Type::Intersection(_)
|
||||
@@ -5745,13 +5745,13 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
right_ty: right,
|
||||
}),
|
||||
},
|
||||
(Type::IntLiteral(_), Type::Instance(_)) => self.infer_binary_type_comparison(
|
||||
(Type::IntLiteral(_), Type::NominalInstance(_)) => self.infer_binary_type_comparison(
|
||||
KnownClass::Int.to_instance(self.db()),
|
||||
op,
|
||||
right,
|
||||
range,
|
||||
),
|
||||
(Type::Instance(_), Type::IntLiteral(_)) => self.infer_binary_type_comparison(
|
||||
(Type::NominalInstance(_), Type::IntLiteral(_)) => self.infer_binary_type_comparison(
|
||||
left,
|
||||
op,
|
||||
KnownClass::Int.to_instance(self.db()),
|
||||
@@ -5877,7 +5877,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
KnownClass::Bytes.to_instance(self.db()),
|
||||
range,
|
||||
),
|
||||
(Type::Tuple(_), Type::Instance(instance))
|
||||
(Type::Tuple(_), Type::NominalInstance(instance))
|
||||
if instance
|
||||
.class()
|
||||
.is_known(self.db(), KnownClass::VersionInfo) =>
|
||||
@@ -5889,7 +5889,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
range,
|
||||
)
|
||||
}
|
||||
(Type::Instance(instance), Type::Tuple(_))
|
||||
(Type::NominalInstance(instance), Type::Tuple(_))
|
||||
if instance
|
||||
.class()
|
||||
.is_known(self.db(), KnownClass::VersionInfo) =>
|
||||
@@ -6275,7 +6275,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
) -> Type<'db> {
|
||||
match (value_ty, slice_ty) {
|
||||
(
|
||||
Type::Instance(instance),
|
||||
Type::NominalInstance(instance),
|
||||
Type::IntLiteral(_) | Type::BooleanLiteral(_) | Type::SliceLiteral(_),
|
||||
) if instance
|
||||
.class()
|
||||
@@ -6576,7 +6576,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||
Err(_) => SliceArg::Unsupported,
|
||||
},
|
||||
Some(Type::BooleanLiteral(b)) => SliceArg::Arg(Some(i32::from(b))),
|
||||
Some(Type::Instance(instance))
|
||||
Some(Type::NominalInstance(instance))
|
||||
if instance.class().is_known(self.db(), KnownClass::NoneType) =>
|
||||
{
|
||||
SliceArg::Arg(None)
|
||||
|
||||
@@ -5,12 +5,12 @@ use crate::Db;
|
||||
|
||||
impl<'db> Type<'db> {
|
||||
pub(crate) const fn instance(class: ClassType<'db>) -> Self {
|
||||
Self::Instance(InstanceType { class })
|
||||
Self::NominalInstance(NominalInstanceType { class })
|
||||
}
|
||||
|
||||
pub(crate) const fn into_instance(self) -> Option<InstanceType<'db>> {
|
||||
pub(crate) const fn into_instance(self) -> Option<NominalInstanceType<'db>> {
|
||||
match self {
|
||||
Type::Instance(instance_type) => Some(instance_type),
|
||||
Type::NominalInstance(instance_type) => Some(instance_type),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,13 @@ impl<'db> Type<'db> {
|
||||
|
||||
/// A type representing the set of runtime objects which are instances of a certain nominal class.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
|
||||
pub struct InstanceType<'db> {
|
||||
// Keep this field private, so that the only way of constructing `InstanceType` instances
|
||||
pub struct NominalInstanceType<'db> {
|
||||
// Keep this field private, so that the only way of constructing `NominalInstanceType` instances
|
||||
// is through the `Type::instance` constructor function.
|
||||
class: ClassType<'db>,
|
||||
}
|
||||
|
||||
impl<'db> InstanceType<'db> {
|
||||
impl<'db> NominalInstanceType<'db> {
|
||||
pub(super) fn class(self) -> ClassType<'db> {
|
||||
self.class
|
||||
}
|
||||
@@ -87,8 +87,8 @@ impl<'db> InstanceType<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> From<InstanceType<'db>> for Type<'db> {
|
||||
fn from(value: InstanceType<'db>) -> Self {
|
||||
Self::Instance(value)
|
||||
impl<'db> From<NominalInstanceType<'db>> for Type<'db> {
|
||||
fn from(value: NominalInstanceType<'db>) -> Self {
|
||||
Self::NominalInstance(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! The `KnownInstance` type.
|
||||
//!
|
||||
//! Despite its name, this is quite a different type from [`super::InstanceType`].
|
||||
//! Despite its name, this is quite a different type from [`super::NominalInstanceType`].
|
||||
//! For the vast majority of instance-types in Python, we cannot say how many possible
|
||||
//! inhabitants there are or could be of that type at runtime. Each variant of the
|
||||
//! [`KnownInstanceType`] enum, however, represents a specific runtime symbol
|
||||
@@ -249,7 +249,7 @@ impl<'db> KnownInstanceType<'db> {
|
||||
///
|
||||
/// For example, the symbol `typing.Literal` is an instance of `typing._SpecialForm`,
|
||||
/// so `KnownInstanceType::Literal.instance_fallback(db)`
|
||||
/// returns `Type::Instance(InstanceType { class: <typing._SpecialForm> })`.
|
||||
/// returns `Type::NominalInstance(NominalInstanceType { class: <typing._SpecialForm> })`.
|
||||
pub(super) fn instance_fallback(self, db: &dyn Db) -> Type {
|
||||
self.class().to_instance(db)
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||
union.map(db, |ty| filter_to_cannot_be_equal(db, *ty, rhs_ty))
|
||||
}
|
||||
// Treat `bool` as `Literal[True, False]`.
|
||||
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Bool) => {
|
||||
Type::NominalInstance(instance) if instance.class().is_known(db, KnownClass::Bool) => {
|
||||
UnionType::from_elements(
|
||||
db,
|
||||
[Type::BooleanLiteral(true), Type::BooleanLiteral(false)]
|
||||
@@ -501,7 +501,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||
|
||||
fn evaluate_expr_ne(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option<Type<'db>> {
|
||||
match (lhs_ty, rhs_ty) {
|
||||
(Type::Instance(instance), Type::IntLiteral(i))
|
||||
(Type::NominalInstance(instance), Type::IntLiteral(i))
|
||||
if instance.class().is_known(self.db, KnownClass::Bool) =>
|
||||
{
|
||||
if i == 0 {
|
||||
|
||||
@@ -16,8 +16,8 @@ impl<'db> SubclassOfType<'db> {
|
||||
/// This method does not always return a [`Type::SubclassOf`] variant.
|
||||
/// If the class object is known to be a final class,
|
||||
/// this method will return a [`Type::ClassLiteral`] variant; this is a more precise type.
|
||||
/// If the class object is `builtins.object`, `Type::Instance(<builtins.type>)` will be returned;
|
||||
/// this is no more precise, but it is exactly equivalent to `type[object]`.
|
||||
/// If the class object is `builtins.object`, `Type::NominalInstance(<builtins.type>)`
|
||||
/// will be returned; this is no more precise, but it is exactly equivalent to `type[object]`.
|
||||
///
|
||||
/// The eager normalization here means that we do not need to worry elsewhere about distinguishing
|
||||
/// between `@final` classes and other classes when dealing with [`Type::SubclassOf`] variants.
|
||||
|
||||
@@ -126,10 +126,12 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
||||
|
||||
(Type::SubclassOf(_), _) => Ordering::Less,
|
||||
(_, Type::SubclassOf(_)) => Ordering::Greater,
|
||||
(Type::Instance(left), Type::Instance(right)) => left.class().cmp(&right.class()),
|
||||
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
|
||||
left.class().cmp(&right.class())
|
||||
}
|
||||
|
||||
(Type::Instance(_), _) => Ordering::Less,
|
||||
(_, Type::Instance(_)) => Ordering::Greater,
|
||||
(Type::NominalInstance(_), _) => Ordering::Less,
|
||||
(_, Type::NominalInstance(_)) => Ordering::Greater,
|
||||
|
||||
(Type::TypeVar(left), Type::TypeVar(right)) => left.cmp(right),
|
||||
(Type::TypeVar(_), _) => Ordering::Less,
|
||||
|
||||
Reference in New Issue
Block a user