mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-19 12:16:43 +00:00
[ty] Rename Type unwrapping methods (#20857)
## Summary Rename "unwrapping" methods on `Type` from e.g. `Type::into_class_literal` to `Type::as_class_literal`. I personally find that name more intuitive, since no transformation of any kind is happening. We are just unwrapping from certain enum variants. An alternative would be `try_as_class_literal`, which would follow the [`strum` naming scheme](https://docs.rs/strum/latest/strum/derive.EnumTryAs.html), but is slightly longer. Also rename `Type::into_callable` to `Type::try_upcast_to_callable`. Note that I intentionally kept names like `FunctionType::into_callable_type`, because those return `CallableType`, not `Option<Type<…>>`. ## Test Plan Pure refactoring
This commit is contained in:
parent
e338d2095e
commit
f73bb45be6
17 changed files with 81 additions and 87 deletions
|
|
@ -1447,7 +1447,7 @@ mod implicit_globals {
|
||||||
fn module_type_symbols<'db>(db: &'db dyn Db) -> smallvec::SmallVec<[ast::name::Name; 8]> {
|
fn module_type_symbols<'db>(db: &'db dyn Db) -> smallvec::SmallVec<[ast::name::Name; 8]> {
|
||||||
let Some(module_type) = KnownClass::ModuleType
|
let Some(module_type) = KnownClass::ModuleType
|
||||||
.to_class_literal(db)
|
.to_class_literal(db)
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
else {
|
else {
|
||||||
// The most likely way we get here is if a user specified a `--custom-typeshed-dir`
|
// The most likely way we get here is if a user specified a `--custom-typeshed-dir`
|
||||||
// without a `types.pyi` stub in the `stdlib/` directory
|
// without a `types.pyi` stub in the `stdlib/` directory
|
||||||
|
|
|
||||||
|
|
@ -854,7 +854,7 @@ impl ReachabilityConstraints {
|
||||||
}
|
}
|
||||||
|
|
||||||
let overloads_iterator =
|
let overloads_iterator =
|
||||||
if let Some(Type::Callable(callable)) = ty.into_callable(db) {
|
if let Some(Type::Callable(callable)) = ty.try_upcast_to_callable(db) {
|
||||||
callable.signatures(db).overloads.iter()
|
callable.signatures(db).overloads.iter()
|
||||||
} else {
|
} else {
|
||||||
return Truthiness::AlwaysFalse.negate_if(!predicate.is_positive);
|
return Truthiness::AlwaysFalse.negate_if(!predicate.is_positive);
|
||||||
|
|
|
||||||
|
|
@ -982,39 +982,39 @@ impl<'db> Type<'db> {
|
||||||
matches!(self, Type::TypeVar(_))
|
matches!(self, Type::TypeVar(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_type_var(self) -> Option<BoundTypeVarInstance<'db>> {
|
pub(crate) const fn as_typevar(self) -> Option<BoundTypeVarInstance<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::TypeVar(bound_typevar) => Some(bound_typevar),
|
Type::TypeVar(bound_typevar) => Some(bound_typevar),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn has_type_var(self, db: &'db dyn Db) -> bool {
|
pub(crate) fn has_typevar(self, db: &'db dyn Db) -> bool {
|
||||||
any_over_type(db, self, &|ty| matches!(ty, Type::TypeVar(_)), false)
|
any_over_type(db, self, &|ty| matches!(ty, Type::TypeVar(_)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_class_literal(self) -> Option<ClassLiteral<'db>> {
|
pub(crate) const fn as_class_literal(self) -> Option<ClassLiteral<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::ClassLiteral(class_type) => Some(class_type),
|
Type::ClassLiteral(class_type) => Some(class_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_type_alias(self) -> Option<TypeAliasType<'db>> {
|
pub(crate) const fn as_type_alias(self) -> Option<TypeAliasType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::KnownInstance(KnownInstanceType::TypeAliasType(type_alias)) => Some(type_alias),
|
Type::KnownInstance(KnownInstanceType::TypeAliasType(type_alias)) => Some(type_alias),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_dynamic(self) -> Option<DynamicType<'db>> {
|
pub(crate) const fn as_dynamic(self) -> Option<DynamicType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::Dynamic(dynamic_type) => Some(dynamic_type),
|
Type::Dynamic(dynamic_type) => Some(dynamic_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn unwrap_as_callable_type(self) -> Option<CallableType<'db>> {
|
pub(crate) const fn as_callable(self) -> Option<CallableType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::Callable(callable_type) => Some(callable_type),
|
Type::Callable(callable_type) => Some(callable_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1022,11 +1022,10 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn expect_dynamic(self) -> DynamicType<'db> {
|
pub(crate) const fn expect_dynamic(self) -> DynamicType<'db> {
|
||||||
self.into_dynamic()
|
self.as_dynamic().expect("Expected a Type::Dynamic variant")
|
||||||
.expect("Expected a Type::Dynamic variant")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_protocol_instance(self) -> Option<ProtocolInstanceType<'db>> {
|
pub(crate) const fn as_protocol_instance(self) -> Option<ProtocolInstanceType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::ProtocolInstance(instance) => Some(instance),
|
Type::ProtocolInstance(instance) => Some(instance),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1035,7 +1034,7 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn expect_class_literal(self) -> ClassLiteral<'db> {
|
pub(crate) fn expect_class_literal(self) -> ClassLiteral<'db> {
|
||||||
self.into_class_literal()
|
self.as_class_literal()
|
||||||
.expect("Expected a Type::ClassLiteral variant")
|
.expect("Expected a Type::ClassLiteral variant")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1048,7 +1047,7 @@ impl<'db> Type<'db> {
|
||||||
matches!(self, Type::ClassLiteral(..))
|
matches!(self, Type::ClassLiteral(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_enum_literal(self) -> Option<EnumLiteralType<'db>> {
|
pub(crate) fn as_enum_literal(self) -> Option<EnumLiteralType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::EnumLiteral(enum_literal) => Some(enum_literal),
|
Type::EnumLiteral(enum_literal) => Some(enum_literal),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1058,7 +1057,7 @@ impl<'db> Type<'db> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn expect_enum_literal(self) -> EnumLiteralType<'db> {
|
pub(crate) fn expect_enum_literal(self) -> EnumLiteralType<'db> {
|
||||||
self.into_enum_literal()
|
self.as_enum_literal()
|
||||||
.expect("Expected a Type::EnumLiteral variant")
|
.expect("Expected a Type::EnumLiteral variant")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1066,7 +1065,7 @@ impl<'db> Type<'db> {
|
||||||
matches!(self, Type::TypedDict(..))
|
matches!(self, Type::TypedDict(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_typed_dict(self) -> Option<TypedDictType<'db>> {
|
pub(crate) fn as_typed_dict(self) -> Option<TypedDictType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::TypedDict(typed_dict) => Some(typed_dict),
|
Type::TypedDict(typed_dict) => Some(typed_dict),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1100,14 +1099,14 @@ impl<'db> Type<'db> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_module_literal(self) -> Option<ModuleLiteralType<'db>> {
|
pub(crate) const fn as_module_literal(self) -> Option<ModuleLiteralType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::ModuleLiteral(module) => Some(module),
|
Type::ModuleLiteral(module) => Some(module),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_union(self) -> Option<UnionType<'db>> {
|
pub(crate) const fn as_union(self) -> Option<UnionType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::Union(union_type) => Some(union_type),
|
Type::Union(union_type) => Some(union_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1117,10 +1116,10 @@ impl<'db> Type<'db> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn expect_union(self) -> UnionType<'db> {
|
pub(crate) fn expect_union(self) -> UnionType<'db> {
|
||||||
self.into_union().expect("Expected a Type::Union variant")
|
self.as_union().expect("Expected a Type::Union variant")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn into_function_literal(self) -> Option<FunctionType<'db>> {
|
pub(crate) const fn as_function_literal(self) -> Option<FunctionType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::FunctionLiteral(function_type) => Some(function_type),
|
Type::FunctionLiteral(function_type) => Some(function_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1130,7 +1129,7 @@ impl<'db> Type<'db> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn expect_function_literal(self) -> FunctionType<'db> {
|
pub(crate) fn expect_function_literal(self) -> FunctionType<'db> {
|
||||||
self.into_function_literal()
|
self.as_function_literal()
|
||||||
.expect("Expected a Type::FunctionLiteral variant")
|
.expect("Expected a Type::FunctionLiteral variant")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1139,7 +1138,7 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_union_of_single_valued(&self, db: &'db dyn Db) -> bool {
|
pub(crate) fn is_union_of_single_valued(&self, db: &'db dyn Db) -> bool {
|
||||||
self.into_union().is_some_and(|union| {
|
self.as_union().is_some_and(|union| {
|
||||||
union.elements(db).iter().all(|ty| {
|
union.elements(db).iter().all(|ty| {
|
||||||
ty.is_single_valued(db)
|
ty.is_single_valued(db)
|
||||||
|| ty.is_bool(db)
|
|| ty.is_bool(db)
|
||||||
|
|
@ -1152,7 +1151,7 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_union_with_single_valued(&self, db: &'db dyn Db) -> bool {
|
pub(crate) fn is_union_with_single_valued(&self, db: &'db dyn Db) -> bool {
|
||||||
self.into_union().is_some_and(|union| {
|
self.as_union().is_some_and(|union| {
|
||||||
union.elements(db).iter().any(|ty| {
|
union.elements(db).iter().any(|ty| {
|
||||||
ty.is_single_valued(db)
|
ty.is_single_valued(db)
|
||||||
|| ty.is_bool(db)
|
|| ty.is_bool(db)
|
||||||
|
|
@ -1164,7 +1163,7 @@ impl<'db> Type<'db> {
|
||||||
|| (self.is_enum(db) && !self.overrides_equality(db))
|
|| (self.is_enum(db) && !self.overrides_equality(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_string_literal(self) -> Option<StringLiteralType<'db>> {
|
pub(crate) fn as_string_literal(self) -> Option<StringLiteralType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::StringLiteral(string_literal) => Some(string_literal),
|
Type::StringLiteral(string_literal) => Some(string_literal),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1404,7 +1403,7 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_callable(self, db: &'db dyn Db) -> Option<Type<'db>> {
|
pub(crate) fn try_upcast_to_callable(self, db: &'db dyn Db) -> Option<Type<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::Callable(_) => Some(self),
|
Type::Callable(_) => Some(self),
|
||||||
|
|
||||||
|
|
@ -1427,7 +1426,7 @@ impl<'db> Type<'db> {
|
||||||
.place;
|
.place;
|
||||||
|
|
||||||
if let Place::Type(ty, Boundness::Bound) = call_symbol {
|
if let Place::Type(ty, Boundness::Bound) = call_symbol {
|
||||||
ty.into_callable(db)
|
ty.try_upcast_to_callable(db)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -1447,13 +1446,13 @@ impl<'db> Type<'db> {
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::Union(union) => union.try_map(db, |element| element.into_callable(db)),
|
Type::Union(union) => union.try_map(db, |element| element.try_upcast_to_callable(db)),
|
||||||
|
|
||||||
Type::EnumLiteral(enum_literal) => {
|
Type::EnumLiteral(enum_literal) => enum_literal
|
||||||
enum_literal.enum_class_instance(db).into_callable(db)
|
.enum_class_instance(db)
|
||||||
}
|
.try_upcast_to_callable(db),
|
||||||
|
|
||||||
Type::TypeAlias(alias) => alias.value_type(db).into_callable(db),
|
Type::TypeAlias(alias) => alias.value_type(db).try_upcast_to_callable(db),
|
||||||
|
|
||||||
Type::KnownBoundMethod(method) => Some(Type::Callable(CallableType::new(
|
Type::KnownBoundMethod(method) => Some(Type::Callable(CallableType::new(
|
||||||
db,
|
db,
|
||||||
|
|
@ -1943,7 +1942,7 @@ impl<'db> Type<'db> {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(_, Type::Callable(_)) => relation_visitor.visit((self, target, relation), || {
|
(_, Type::Callable(_)) => relation_visitor.visit((self, target, relation), || {
|
||||||
self.into_callable(db).when_some_and(|callable| {
|
self.try_upcast_to_callable(db).when_some_and(|callable| {
|
||||||
callable.has_relation_to_impl(
|
callable.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
target,
|
target,
|
||||||
|
|
@ -8083,7 +8082,7 @@ impl<'db> TypeVarInstance<'db> {
|
||||||
TypeVarBoundOrConstraints::UpperBound(upper_bound.to_instance(db)?)
|
TypeVarBoundOrConstraints::UpperBound(upper_bound.to_instance(db)?)
|
||||||
}
|
}
|
||||||
TypeVarBoundOrConstraints::Constraints(constraints) => {
|
TypeVarBoundOrConstraints::Constraints(constraints) => {
|
||||||
TypeVarBoundOrConstraints::Constraints(constraints.to_instance(db)?.into_union()?)
|
TypeVarBoundOrConstraints::Constraints(constraints.to_instance(db)?.as_union()?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let identity = TypeVarIdentity::new(
|
let identity = TypeVarIdentity::new(
|
||||||
|
|
@ -8131,7 +8130,7 @@ impl<'db> TypeVarInstance<'db> {
|
||||||
DefinitionKind::TypeVar(typevar) => {
|
DefinitionKind::TypeVar(typevar) => {
|
||||||
let typevar_node = typevar.node(&module);
|
let typevar_node = typevar.node(&module);
|
||||||
definition_expression_type(db, definition, typevar_node.bound.as_ref()?)
|
definition_expression_type(db, definition, typevar_node.bound.as_ref()?)
|
||||||
.into_union()?
|
.as_union()?
|
||||||
}
|
}
|
||||||
// legacy typevar
|
// legacy typevar
|
||||||
DefinitionKind::Assignment(assignment) => {
|
DefinitionKind::Assignment(assignment) => {
|
||||||
|
|
@ -10713,7 +10712,7 @@ impl<'db> TypeAliasType<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_pep_695_type_alias(self) -> Option<PEP695TypeAliasType<'db>> {
|
pub(crate) fn as_pep_695_type_alias(self) -> Option<PEP695TypeAliasType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
TypeAliasType::PEP695(type_alias) => Some(type_alias),
|
TypeAliasType::PEP695(type_alias) => Some(type_alias),
|
||||||
TypeAliasType::ManualPEP695(_) => None,
|
TypeAliasType::ManualPEP695(_) => None,
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,7 @@ impl<'db> UnionBuilder<'db> {
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(UnionElement::to_type_element)
|
.filter_map(UnionElement::to_type_element)
|
||||||
.filter_map(Type::into_enum_literal)
|
.filter_map(Type::as_enum_literal)
|
||||||
.map(|literal| literal.name(self.db).clone())
|
.map(|literal| literal.name(self.db).clone())
|
||||||
.chain(std::iter::once(enum_member_to_add.name(self.db).clone()))
|
.chain(std::iter::once(enum_member_to_add.name(self.db).clone()))
|
||||||
.collect::<FxOrderSet<_>>();
|
.collect::<FxOrderSet<_>>();
|
||||||
|
|
@ -650,7 +650,7 @@ impl<'db> IntersectionBuilder<'db> {
|
||||||
for intersection in &self.intersections {
|
for intersection in &self.intersections {
|
||||||
if intersection.negative.iter().any(|negative| {
|
if intersection.negative.iter().any(|negative| {
|
||||||
negative
|
negative
|
||||||
.into_enum_literal()
|
.as_enum_literal()
|
||||||
.is_some_and(|lit| lit.enum_class_instance(self.db) == ty)
|
.is_some_and(|lit| lit.enum_class_instance(self.db) == ty)
|
||||||
}) {
|
}) {
|
||||||
contains_enum_literal_as_negative_element = true;
|
contains_enum_literal_as_negative_element = true;
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ impl<'db> Bindings<'db> {
|
||||||
..,
|
..,
|
||||||
] if property.getter(db).is_some_and(|getter| {
|
] if property.getter(db).is_some_and(|getter| {
|
||||||
getter
|
getter
|
||||||
.into_function_literal()
|
.as_function_literal()
|
||||||
.is_some_and(|f| f.name(db) == "__name__")
|
.is_some_and(|f| f.name(db) == "__name__")
|
||||||
}) =>
|
}) =>
|
||||||
{
|
{
|
||||||
|
|
@ -392,7 +392,7 @@ impl<'db> Bindings<'db> {
|
||||||
] => {
|
] => {
|
||||||
match property
|
match property
|
||||||
.getter(db)
|
.getter(db)
|
||||||
.and_then(Type::into_function_literal)
|
.and_then(Type::as_function_literal)
|
||||||
.map(|f| f.name(db).as_str())
|
.map(|f| f.name(db).as_str())
|
||||||
{
|
{
|
||||||
Some("__name__") => {
|
Some("__name__") => {
|
||||||
|
|
@ -785,7 +785,7 @@ impl<'db> Bindings<'db> {
|
||||||
// be a "(specialised) protocol class", but `typing.is_protocol(SupportsAbs[int])` returns
|
// be a "(specialised) protocol class", but `typing.is_protocol(SupportsAbs[int])` returns
|
||||||
// `False` at runtime, so we do not set the return type to `Literal[True]` in this case.
|
// `False` at runtime, so we do not set the return type to `Literal[True]` in this case.
|
||||||
overload.set_return_type(Type::BooleanLiteral(
|
overload.set_return_type(Type::BooleanLiteral(
|
||||||
ty.into_class_literal()
|
ty.as_class_literal()
|
||||||
.is_some_and(|class| class.is_protocol(db)),
|
.is_some_and(|class| class.is_protocol(db)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -817,7 +817,7 @@ impl<'db> Bindings<'db> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(attr_name) = attr_name.into_string_literal() else {
|
let Some(attr_name) = attr_name.as_string_literal() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1724,7 +1724,7 @@ impl<'db> ClassLiteral<'db> {
|
||||||
/// Determine if this is an abstract class.
|
/// Determine if this is an abstract class.
|
||||||
pub(super) fn is_abstract(self, db: &'db dyn Db) -> bool {
|
pub(super) fn is_abstract(self, db: &'db dyn Db) -> bool {
|
||||||
self.metaclass(db)
|
self.metaclass(db)
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
.is_some_and(|metaclass| metaclass.is_known(db, KnownClass::ABCMeta))
|
.is_some_and(|metaclass| metaclass.is_known(db, KnownClass::ABCMeta))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1758,7 +1758,7 @@ impl<'db> ClassLiteral<'db> {
|
||||||
) -> impl Iterator<Item = KnownFunction> + 'db {
|
) -> impl Iterator<Item = KnownFunction> + 'db {
|
||||||
self.decorators(db)
|
self.decorators(db)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|deco| deco.into_function_literal())
|
.filter_map(|deco| deco.as_function_literal())
|
||||||
.filter_map(|decorator| decorator.known(db))
|
.filter_map(|decorator| decorator.known(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2398,7 +2398,7 @@ impl<'db> ClassLiteral<'db> {
|
||||||
(CodeGeneratorKind::NamedTuple, name) if name != "__init__" => {
|
(CodeGeneratorKind::NamedTuple, name) if name != "__init__" => {
|
||||||
KnownClass::NamedTupleFallback
|
KnownClass::NamedTupleFallback
|
||||||
.to_class_literal(db)
|
.to_class_literal(db)
|
||||||
.into_class_literal()?
|
.as_class_literal()?
|
||||||
.own_class_member(db, self.inherited_generic_context(db), None, name)
|
.own_class_member(db, self.inherited_generic_context(db), None, name)
|
||||||
.ignore_possibly_unbound()
|
.ignore_possibly_unbound()
|
||||||
.map(|ty| {
|
.map(|ty| {
|
||||||
|
|
@ -5250,7 +5250,7 @@ impl KnownClass {
|
||||||
};
|
};
|
||||||
|
|
||||||
overload.set_return_type(Type::KnownInstance(KnownInstanceType::Deprecated(
|
overload.set_return_type(Type::KnownInstance(KnownInstanceType::Deprecated(
|
||||||
DeprecatedInstance::new(db, message.into_string_literal()),
|
DeprecatedInstance::new(db, message.as_string_literal()),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5270,7 +5270,7 @@ impl KnownClass {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(name) = name.into_string_literal() else {
|
let Some(name) = name.as_string_literal() else {
|
||||||
if let Some(builder) =
|
if let Some(builder) =
|
||||||
context.report_lint(&INVALID_TYPE_ALIAS_TYPE, call_expression)
|
context.report_lint(&INVALID_TYPE_ALIAS_TYPE, call_expression)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ impl<'db, 'ast> InferContext<'db, 'ast> {
|
||||||
.ancestor_scopes(scope_id)
|
.ancestor_scopes(scope_id)
|
||||||
.filter_map(|(_, scope)| scope.node().as_function())
|
.filter_map(|(_, scope)| scope.node().as_function())
|
||||||
.map(|node| binding_type(self.db, index.expect_single_definition(node)))
|
.map(|node| binding_type(self.db, index.expect_single_definition(node)))
|
||||||
.filter_map(Type::into_function_literal);
|
.filter_map(Type::as_function_literal);
|
||||||
|
|
||||||
// Iterate over all functions and test if any is decorated with `@no_type_check`.
|
// Iterate over all functions and test if any is decorated with `@no_type_check`.
|
||||||
function_scope_tys.any(|function_ty| {
|
function_scope_tys.any(|function_ty| {
|
||||||
|
|
|
||||||
|
|
@ -1145,7 +1145,7 @@ fn is_instance_truthiness<'db>(
|
||||||
fn is_mode_with_nontrivial_return_type<'db>(db: &'db dyn Db, mode: Type<'db>) -> bool {
|
fn is_mode_with_nontrivial_return_type<'db>(db: &'db dyn Db, mode: Type<'db>) -> bool {
|
||||||
// Return true for any mode that doesn't match typeshed's
|
// Return true for any mode that doesn't match typeshed's
|
||||||
// `OpenTextMode` type alias (<https://github.com/python/typeshed/blob/6937a9b193bfc2f0696452d58aad96d7627aa29a/stdlib/_typeshed/__init__.pyi#L220>).
|
// `OpenTextMode` type alias (<https://github.com/python/typeshed/blob/6937a9b193bfc2f0696452d58aad96d7627aa29a/stdlib/_typeshed/__init__.pyi#L220>).
|
||||||
mode.into_string_literal().is_none_or(|mode| {
|
mode.as_string_literal().is_none_or(|mode| {
|
||||||
!matches!(
|
!matches!(
|
||||||
mode.value(db),
|
mode.value(db),
|
||||||
"r+" | "+r"
|
"r+" | "+r"
|
||||||
|
|
@ -1557,7 +1557,7 @@ impl KnownFunction {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut diagnostic = if let Some(message) = message
|
let mut diagnostic = if let Some(message) = message
|
||||||
.and_then(Type::into_string_literal)
|
.and_then(Type::as_string_literal)
|
||||||
.map(|s| s.value(db))
|
.map(|s| s.value(db))
|
||||||
{
|
{
|
||||||
builder.into_diagnostic(format_args!("Static assertion error: {message}"))
|
builder.into_diagnostic(format_args!("Static assertion error: {message}"))
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub(crate) fn enclosing_generic_contexts<'db>(
|
||||||
NodeWithScopeKind::Class(class) => {
|
NodeWithScopeKind::Class(class) => {
|
||||||
let definition = index.expect_single_definition(class);
|
let definition = index.expect_single_definition(class);
|
||||||
binding_type(db, definition)
|
binding_type(db, definition)
|
||||||
.into_class_literal()?
|
.as_class_literal()?
|
||||||
.generic_context(db)
|
.generic_context(db)
|
||||||
}
|
}
|
||||||
NodeWithScopeKind::Function(function) => {
|
NodeWithScopeKind::Function(function) => {
|
||||||
|
|
@ -43,15 +43,15 @@ pub(crate) fn enclosing_generic_contexts<'db>(
|
||||||
infer_definition_types(db, definition)
|
infer_definition_types(db, definition)
|
||||||
.undecorated_type()
|
.undecorated_type()
|
||||||
.expect("function should have undecorated type")
|
.expect("function should have undecorated type")
|
||||||
.into_function_literal()?
|
.as_function_literal()?
|
||||||
.last_definition_signature(db)
|
.last_definition_signature(db)
|
||||||
.generic_context
|
.generic_context
|
||||||
}
|
}
|
||||||
NodeWithScopeKind::TypeAlias(type_alias) => {
|
NodeWithScopeKind::TypeAlias(type_alias) => {
|
||||||
let definition = index.expect_single_definition(type_alias);
|
let definition = index.expect_single_definition(type_alias);
|
||||||
binding_type(db, definition)
|
binding_type(db, definition)
|
||||||
.into_type_alias()?
|
.as_type_alias()?
|
||||||
.into_pep_695_type_alias()?
|
.as_pep_695_type_alias()?
|
||||||
.generic_context(db)
|
.generic_context(db)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -1284,7 +1284,7 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
let types_have_typevars = formal_union
|
let types_have_typevars = formal_union
|
||||||
.elements(self.db)
|
.elements(self.db)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|ty| ty.has_type_var(self.db));
|
.filter(|ty| ty.has_typevar(self.db));
|
||||||
let Ok(Type::TypeVar(formal_bound_typevar)) = types_have_typevars.exactly_one()
|
let Ok(Type::TypeVar(formal_bound_typevar)) = types_have_typevars.exactly_one()
|
||||||
else {
|
else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -1305,7 +1305,7 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
// type. (Note that we've already handled above the case where the actual is
|
// type. (Note that we've already handled above the case where the actual is
|
||||||
// assignable to any _non-typevar_ union element.)
|
// assignable to any _non-typevar_ union element.)
|
||||||
let bound_typevars =
|
let bound_typevars =
|
||||||
(formal.elements(self.db).iter()).filter_map(|ty| ty.into_type_var());
|
(formal.elements(self.db).iter()).filter_map(|ty| ty.as_typevar());
|
||||||
if let Ok(bound_typevar) = bound_typevars.exactly_one() {
|
if let Ok(bound_typevar) = bound_typevars.exactly_one() {
|
||||||
self.add_type_mapping(bound_typevar, actual);
|
self.add_type_mapping(bound_typevar, actual);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -777,7 +777,7 @@ pub fn definitions_for_keyword_argument<'db>(
|
||||||
|
|
||||||
let mut resolved_definitions = Vec::new();
|
let mut resolved_definitions = Vec::new();
|
||||||
|
|
||||||
if let Some(Type::Callable(callable_type)) = func_type.into_callable(db) {
|
if let Some(Type::Callable(callable_type)) = func_type.try_upcast_to_callable(db) {
|
||||||
let signatures = callable_type.signatures(db);
|
let signatures = callable_type.signatures(db);
|
||||||
|
|
||||||
// For each signature, find the parameter with the matching name
|
// For each signature, find the parameter with the matching name
|
||||||
|
|
@ -872,7 +872,7 @@ pub fn call_signature_details<'db>(
|
||||||
let func_type = call_expr.func.inferred_type(model);
|
let func_type = call_expr.func.inferred_type(model);
|
||||||
|
|
||||||
// Use into_callable to handle all the complex type conversions
|
// Use into_callable to handle all the complex type conversions
|
||||||
if let Some(callable_type) = func_type.into_callable(db) {
|
if let Some(callable_type) = func_type.try_upcast_to_callable(db) {
|
||||||
let call_arguments =
|
let call_arguments =
|
||||||
CallArguments::from_arguments(&call_expr.arguments, |_, splatted_value| {
|
CallArguments::from_arguments(&call_expr.arguments, |_, splatted_value| {
|
||||||
splatted_value.inferred_type(model)
|
splatted_value.inferred_type(model)
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,7 @@ pub(crate) fn nearest_enclosing_class<'db>(
|
||||||
infer_definition_types(db, definition)
|
infer_definition_types(db, definition)
|
||||||
.declaration_type(definition)
|
.declaration_type(definition)
|
||||||
.inner_type()
|
.inner_type()
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -514,7 +514,7 @@ pub(crate) fn nearest_enclosing_function<'db>(
|
||||||
inference
|
inference
|
||||||
.undecorated_type()
|
.undecorated_type()
|
||||||
.unwrap_or_else(|| inference.declaration_type(definition).inner_type())
|
.unwrap_or_else(|| inference.declaration_type(definition).inner_type())
|
||||||
.into_function_literal()
|
.as_function_literal()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
// Filter out class literals that result from imports
|
// Filter out class literals that result from imports
|
||||||
if let DefinitionKind::Class(class) = definition.kind(self.db()) {
|
if let DefinitionKind::Class(class) = definition.kind(self.db()) {
|
||||||
ty.inner_type()
|
ty.inner_type()
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
.map(|class_literal| (class_literal, class.node(self.module())))
|
.map(|class_literal| (class_literal, class.node(self.module())))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -939,7 +939,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
if !matches!(definition.kind(self.db()), DefinitionKind::Function(_)) {
|
if !matches!(definition.kind(self.db()), DefinitionKind::Function(_)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let function = ty.inner_type().into_function_literal()?;
|
let function = ty.inner_type().as_function_literal()?;
|
||||||
if function.has_known_decorator(self.db(), FunctionDecorators::OVERLOAD) {
|
if function.has_known_decorator(self.db(), FunctionDecorators::OVERLOAD) {
|
||||||
Some(definition.place(self.db()))
|
Some(definition.place(self.db()))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2200,12 +2200,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
{
|
{
|
||||||
Ok(return_ty) => {
|
Ok(return_ty) => {
|
||||||
let is_input_function_like = inferred_ty
|
let is_input_function_like = inferred_ty
|
||||||
.into_callable(self.db())
|
.try_upcast_to_callable(self.db())
|
||||||
.and_then(Type::unwrap_as_callable_type)
|
.and_then(Type::as_callable)
|
||||||
.is_some_and(|callable| callable.is_function_like(self.db()));
|
.is_some_and(|callable| callable.is_function_like(self.db()));
|
||||||
if is_input_function_like
|
if is_input_function_like && let Some(callable_type) = return_ty.as_callable() {
|
||||||
&& let Some(callable_type) = return_ty.unwrap_as_callable_type()
|
|
||||||
{
|
|
||||||
// When a method on a class is decorated with a function that returns a `Callable`, assume that
|
// When a method on a class is decorated with a function that returns a `Callable`, assume that
|
||||||
// the returned callable is also function-like. See "Decorating a method with a `Callable`-typed
|
// the returned callable is also function-like. See "Decorating a method with a `Callable`-typed
|
||||||
// decorator" in `callables_as_descriptors.md` for the extended explanation.
|
// decorator" in `callables_as_descriptors.md` for the extended explanation.
|
||||||
|
|
@ -2546,7 +2544,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
for decorator in decorator_list {
|
for decorator in decorator_list {
|
||||||
let decorator_ty = self.infer_decorator(decorator);
|
let decorator_ty = self.infer_decorator(decorator);
|
||||||
if decorator_ty
|
if decorator_ty
|
||||||
.into_function_literal()
|
.as_function_literal()
|
||||||
.is_some_and(|function| function.is_known(self.db(), KnownFunction::Dataclass))
|
.is_some_and(|function| function.is_known(self.db(), KnownFunction::Dataclass))
|
||||||
{
|
{
|
||||||
dataclass_params = Some(DataclassParams::default());
|
dataclass_params = Some(DataclassParams::default());
|
||||||
|
|
@ -3342,8 +3340,8 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
let assigned_d = assigned_ty.display(db);
|
let assigned_d = assigned_ty.display(db);
|
||||||
let value_d = value_ty.display(db);
|
let value_d = value_ty.display(db);
|
||||||
|
|
||||||
if let Some(typed_dict) = value_ty.into_typed_dict() {
|
if let Some(typed_dict) = value_ty.as_typed_dict() {
|
||||||
if let Some(key) = slice_ty.into_string_literal() {
|
if let Some(key) = slice_ty.as_string_literal() {
|
||||||
let key = key.value(self.db());
|
let key = key.value(self.db());
|
||||||
validate_typed_dict_key_assignment(
|
validate_typed_dict_key_assignment(
|
||||||
&self.context,
|
&self.context,
|
||||||
|
|
@ -4056,7 +4054,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let typevar_class = callable_type
|
let typevar_class = callable_type
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
.and_then(|cls| cls.known(self.db()))
|
.and_then(|cls| cls.known(self.db()))
|
||||||
.filter(|cls| {
|
.filter(|cls| {
|
||||||
matches!(cls, KnownClass::TypeVar | KnownClass::ExtensionsTypeVar)
|
matches!(cls, KnownClass::TypeVar | KnownClass::ExtensionsTypeVar)
|
||||||
|
|
@ -4278,10 +4276,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(name_param) = name_param_ty
|
let Some(name_param) = name_param_ty.as_string_literal().map(|name| name.value(db)) else {
|
||||||
.into_string_literal()
|
|
||||||
.map(|name| name.value(db))
|
|
||||||
else {
|
|
||||||
return error(
|
return error(
|
||||||
&self.context,
|
&self.context,
|
||||||
"The first argument to `TypeVar` must be a string literal.",
|
"The first argument to `TypeVar` must be a string literal.",
|
||||||
|
|
@ -5036,7 +5031,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
// Avoid looking up attributes on a module if a module imports from itself
|
// Avoid looking up attributes on a module if a module imports from itself
|
||||||
// (e.g. `from parent import submodule` inside the `parent` module).
|
// (e.g. `from parent import submodule` inside the `parent` module).
|
||||||
let import_is_self_referential = module_ty
|
let import_is_self_referential = module_ty
|
||||||
.into_module_literal()
|
.as_module_literal()
|
||||||
.is_some_and(|module| Some(self.file()) == module.module(self.db()).file(self.db()));
|
.is_some_and(|module| Some(self.file()) == module.module(self.db()).file(self.db()));
|
||||||
|
|
||||||
// First try loading the requested attribute from the module.
|
// First try loading the requested attribute from the module.
|
||||||
|
|
@ -5871,7 +5866,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
} = dict;
|
} = dict;
|
||||||
|
|
||||||
// Validate `TypedDict` dictionary literal assignments.
|
// Validate `TypedDict` dictionary literal assignments.
|
||||||
if let Some(typed_dict) = tcx.annotation.and_then(Type::into_typed_dict)
|
if let Some(typed_dict) = tcx.annotation.and_then(Type::as_typed_dict)
|
||||||
&& let Some(ty) = self.infer_typed_dict_expression(dict, typed_dict)
|
&& let Some(ty) = self.infer_typed_dict_expression(dict, typed_dict)
|
||||||
{
|
{
|
||||||
return ty;
|
return ty;
|
||||||
|
|
@ -6595,10 +6590,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.infer_all_argument_types(arguments, &mut call_arguments, &bindings);
|
self.infer_all_argument_types(arguments, &mut call_arguments, &bindings);
|
||||||
|
|
||||||
// Validate `TypedDict` constructor calls after argument type inference
|
// Validate `TypedDict` constructor calls after argument type inference
|
||||||
if let Some(class_literal) = callable_type.into_class_literal() {
|
if let Some(class_literal) = callable_type.as_class_literal() {
|
||||||
if class_literal.is_typed_dict(self.db()) {
|
if class_literal.is_typed_dict(self.db()) {
|
||||||
let typed_dict_type = Type::typed_dict(ClassType::NonGeneric(class_literal));
|
let typed_dict_type = Type::typed_dict(ClassType::NonGeneric(class_literal));
|
||||||
if let Some(typed_dict) = typed_dict_type.into_typed_dict() {
|
if let Some(typed_dict) = typed_dict_type.as_typed_dict() {
|
||||||
validate_typed_dict_constructor(
|
validate_typed_dict_constructor(
|
||||||
&self.context,
|
&self.context,
|
||||||
typed_dict,
|
typed_dict,
|
||||||
|
|
@ -9459,7 +9454,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallErrorKind::BindingError => {
|
CallErrorKind::BindingError => {
|
||||||
if let Some(typed_dict) = value_ty.into_typed_dict() {
|
if let Some(typed_dict) = value_ty.as_typed_dict() {
|
||||||
let slice_node = subscript.slice.as_ref();
|
let slice_node = subscript.slice.as_ref();
|
||||||
|
|
||||||
report_invalid_key_on_typed_dict(
|
report_invalid_key_on_typed_dict(
|
||||||
|
|
@ -9566,7 +9561,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
|
|
||||||
// TODO: properly handle old-style generics; get rid of this temporary hack
|
// TODO: properly handle old-style generics; get rid of this temporary hack
|
||||||
if !value_ty
|
if !value_ty
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
.is_some_and(|class| class.iter_mro(db, None).contains(&ClassBase::Generic))
|
.is_some_and(|class| class.iter_mro(db, None).contains(&ClassBase::Generic))
|
||||||
{
|
{
|
||||||
report_non_subscriptable(context, value_node.into(), value_ty, "__class_getitem__");
|
report_non_subscriptable(context, value_node.into(), value_ty, "__class_getitem__");
|
||||||
|
|
|
||||||
|
|
@ -1157,7 +1157,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
|
||||||
|
|
||||||
let argument_type = self.infer_expression(&arguments[0], TypeContext::default());
|
let argument_type = self.infer_expression(&arguments[0], TypeContext::default());
|
||||||
|
|
||||||
let Some(callable_type) = argument_type.into_callable(db) else {
|
let Some(callable_type) = argument_type.try_upcast_to_callable(db) else {
|
||||||
if let Some(builder) = self
|
if let Some(builder) = self
|
||||||
.context
|
.context
|
||||||
.report_lint(&INVALID_TYPE_FORM, arguments_slice)
|
.report_lint(&INVALID_TYPE_FORM, arguments_slice)
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ impl<'db> Type<'db> {
|
||||||
// from a protocol `Q` to be a subtype of `Q` to be a subtype of `Q` if it overrides
|
// from a protocol `Q` to be a subtype of `Q` to be a subtype of `Q` if it overrides
|
||||||
// `Q`'s members in a Liskov-incompatible way.
|
// `Q`'s members in a Liskov-incompatible way.
|
||||||
let type_to_test = self
|
let type_to_test = self
|
||||||
.into_protocol_instance()
|
.as_protocol_instance()
|
||||||
.and_then(ProtocolInstanceType::as_nominal_type)
|
.and_then(ProtocolInstanceType::as_nominal_type)
|
||||||
.map(Type::NominalInstance)
|
.map(Type::NominalInstance)
|
||||||
.unwrap_or(self);
|
.unwrap_or(self);
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||||
// Add the narrowed values from the RHS first, to keep literals before broader types.
|
// Add the narrowed values from the RHS first, to keep literals before broader types.
|
||||||
builder = builder.add(rhs_values);
|
builder = builder.add(rhs_values);
|
||||||
|
|
||||||
if let Some(lhs_union) = lhs_ty.into_union() {
|
if let Some(lhs_union) = lhs_ty.as_union() {
|
||||||
for element in lhs_union.elements(self.db) {
|
for element in lhs_union.elements(self.db) {
|
||||||
// Keep only the non-single-valued portion of the original type.
|
// Keep only the non-single-valued portion of the original type.
|
||||||
if !element.is_single_valued(self.db)
|
if !element.is_single_valued(self.db)
|
||||||
|
|
@ -671,7 +671,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||||
let mut single_builder = UnionBuilder::new(self.db);
|
let mut single_builder = UnionBuilder::new(self.db);
|
||||||
let mut rest_builder = UnionBuilder::new(self.db);
|
let mut rest_builder = UnionBuilder::new(self.db);
|
||||||
|
|
||||||
if let Some(lhs_union) = lhs_ty.into_union() {
|
if let Some(lhs_union) = lhs_ty.as_union() {
|
||||||
for element in lhs_union.elements(self.db) {
|
for element in lhs_union.elements(self.db) {
|
||||||
if element.is_single_valued(self.db)
|
if element.is_single_valued(self.db)
|
||||||
|| element.is_literal_string()
|
|| element.is_literal_string()
|
||||||
|
|
@ -840,7 +840,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||||
let callable_type = inference.expression_type(&**callable);
|
let callable_type = inference.expression_type(&**callable);
|
||||||
|
|
||||||
if callable_type
|
if callable_type
|
||||||
.into_class_literal()
|
.as_class_literal()
|
||||||
.is_some_and(|c| c.is_known(self.db, KnownClass::Type))
|
.is_some_and(|c| c.is_known(self.db, KnownClass::Type))
|
||||||
{
|
{
|
||||||
let place = self.expect_place(&target);
|
let place = self.expect_place(&target);
|
||||||
|
|
@ -903,7 +903,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||||
if function == KnownFunction::HasAttr {
|
if function == KnownFunction::HasAttr {
|
||||||
let attr = inference
|
let attr = inference
|
||||||
.expression_type(second_arg)
|
.expression_type(second_arg)
|
||||||
.into_string_literal()?
|
.as_string_literal()?
|
||||||
.value(self.db);
|
.value(self.db);
|
||||||
|
|
||||||
if !is_identifier(attr) {
|
if !is_identifier(attr) {
|
||||||
|
|
|
||||||
|
|
@ -641,7 +641,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
// unfortunately not sufficient to obtain the `Callable` supertypes of these types, due to the
|
// unfortunately not sufficient to obtain the `Callable` supertypes of these types, due to the
|
||||||
// complex interaction between `__new__`, `__init__` and metaclass `__call__`.
|
// complex interaction between `__new__`, `__init__` and metaclass `__call__`.
|
||||||
let attribute_type = if self.name == "__call__" {
|
let attribute_type = if self.name == "__call__" {
|
||||||
let Some(attribute_type) = other.into_callable(db) else {
|
let Some(attribute_type) = other.try_upcast_to_callable(db) else {
|
||||||
return ConstraintSet::from(false);
|
return ConstraintSet::from(false);
|
||||||
};
|
};
|
||||||
attribute_type
|
attribute_type
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ fn infer_method_information<'db>(
|
||||||
let method = infer_definition_types(db, definition)
|
let method = infer_definition_types(db, definition)
|
||||||
.declaration_type(definition)
|
.declaration_type(definition)
|
||||||
.inner_type()
|
.inner_type()
|
||||||
.into_function_literal()?;
|
.as_function_literal()?;
|
||||||
|
|
||||||
let class_def = index.expect_single_definition(class_node);
|
let class_def = index.expect_single_definition(class_node);
|
||||||
let (class_literal, class_is_generic) = match infer_definition_types(db, class_def)
|
let (class_literal, class_is_generic) = match infer_definition_types(db, class_def)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue