[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:
David Peter 2025-10-14 09:53:29 +02:00 committed by GitHub
parent e338d2095e
commit f73bb45be6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 81 additions and 87 deletions

View file

@ -1447,7 +1447,7 @@ mod implicit_globals {
fn module_type_symbols<'db>(db: &'db dyn Db) -> smallvec::SmallVec<[ast::name::Name; 8]> {
let Some(module_type) = KnownClass::ModuleType
.to_class_literal(db)
.into_class_literal()
.as_class_literal()
else {
// 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

View file

@ -854,7 +854,7 @@ impl ReachabilityConstraints {
}
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()
} else {
return Truthiness::AlwaysFalse.negate_if(!predicate.is_positive);

View file

@ -982,39 +982,39 @@ impl<'db> Type<'db> {
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 {
Type::TypeVar(bound_typevar) => Some(bound_typevar),
_ => 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)
}
pub(crate) const fn into_class_literal(self) -> Option<ClassLiteral<'db>> {
pub(crate) const fn as_class_literal(self) -> Option<ClassLiteral<'db>> {
match self {
Type::ClassLiteral(class_type) => Some(class_type),
_ => 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 {
Type::KnownInstance(KnownInstanceType::TypeAliasType(type_alias)) => Some(type_alias),
_ => None,
}
}
pub(crate) const fn into_dynamic(self) -> Option<DynamicType<'db>> {
pub(crate) const fn as_dynamic(self) -> Option<DynamicType<'db>> {
match self {
Type::Dynamic(dynamic_type) => Some(dynamic_type),
_ => 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 {
Type::Callable(callable_type) => Some(callable_type),
_ => None,
@ -1022,11 +1022,10 @@ impl<'db> Type<'db> {
}
pub(crate) const fn expect_dynamic(self) -> DynamicType<'db> {
self.into_dynamic()
.expect("Expected a Type::Dynamic variant")
self.as_dynamic().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 {
Type::ProtocolInstance(instance) => Some(instance),
_ => None,
@ -1035,7 +1034,7 @@ impl<'db> Type<'db> {
#[track_caller]
pub(crate) fn expect_class_literal(self) -> ClassLiteral<'db> {
self.into_class_literal()
self.as_class_literal()
.expect("Expected a Type::ClassLiteral variant")
}
@ -1048,7 +1047,7 @@ impl<'db> Type<'db> {
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 {
Type::EnumLiteral(enum_literal) => Some(enum_literal),
_ => None,
@ -1058,7 +1057,7 @@ impl<'db> Type<'db> {
#[cfg(test)]
#[track_caller]
pub(crate) fn expect_enum_literal(self) -> EnumLiteralType<'db> {
self.into_enum_literal()
self.as_enum_literal()
.expect("Expected a Type::EnumLiteral variant")
}
@ -1066,7 +1065,7 @@ impl<'db> Type<'db> {
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 {
Type::TypedDict(typed_dict) => Some(typed_dict),
_ => 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 {
Type::ModuleLiteral(module) => Some(module),
_ => None,
}
}
pub(crate) const fn into_union(self) -> Option<UnionType<'db>> {
pub(crate) const fn as_union(self) -> Option<UnionType<'db>> {
match self {
Type::Union(union_type) => Some(union_type),
_ => None,
@ -1117,10 +1116,10 @@ impl<'db> Type<'db> {
#[cfg(test)]
#[track_caller]
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 {
Type::FunctionLiteral(function_type) => Some(function_type),
_ => None,
@ -1130,7 +1129,7 @@ impl<'db> Type<'db> {
#[cfg(test)]
#[track_caller]
pub(crate) fn expect_function_literal(self) -> FunctionType<'db> {
self.into_function_literal()
self.as_function_literal()
.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 {
self.into_union().is_some_and(|union| {
self.as_union().is_some_and(|union| {
union.elements(db).iter().all(|ty| {
ty.is_single_valued(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 {
self.into_union().is_some_and(|union| {
self.as_union().is_some_and(|union| {
union.elements(db).iter().any(|ty| {
ty.is_single_valued(db)
|| ty.is_bool(db)
@ -1164,7 +1163,7 @@ impl<'db> Type<'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 {
Type::StringLiteral(string_literal) => Some(string_literal),
_ => 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 {
Type::Callable(_) => Some(self),
@ -1427,7 +1426,7 @@ impl<'db> Type<'db> {
.place;
if let Place::Type(ty, Boundness::Bound) = call_symbol {
ty.into_callable(db)
ty.try_upcast_to_callable(db)
} else {
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) => {
enum_literal.enum_class_instance(db).into_callable(db)
}
Type::EnumLiteral(enum_literal) => enum_literal
.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(
db,
@ -1943,7 +1942,7 @@ impl<'db> Type<'db> {
}),
(_, 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(
db,
target,
@ -8083,7 +8082,7 @@ impl<'db> TypeVarInstance<'db> {
TypeVarBoundOrConstraints::UpperBound(upper_bound.to_instance(db)?)
}
TypeVarBoundOrConstraints::Constraints(constraints) => {
TypeVarBoundOrConstraints::Constraints(constraints.to_instance(db)?.into_union()?)
TypeVarBoundOrConstraints::Constraints(constraints.to_instance(db)?.as_union()?)
}
};
let identity = TypeVarIdentity::new(
@ -8131,7 +8130,7 @@ impl<'db> TypeVarInstance<'db> {
DefinitionKind::TypeVar(typevar) => {
let typevar_node = typevar.node(&module);
definition_expression_type(db, definition, typevar_node.bound.as_ref()?)
.into_union()?
.as_union()?
}
// legacy typevar
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 {
TypeAliasType::PEP695(type_alias) => Some(type_alias),
TypeAliasType::ManualPEP695(_) => None,

View file

@ -421,7 +421,7 @@ impl<'db> UnionBuilder<'db> {
.elements
.iter()
.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())
.chain(std::iter::once(enum_member_to_add.name(self.db).clone()))
.collect::<FxOrderSet<_>>();
@ -650,7 +650,7 @@ impl<'db> IntersectionBuilder<'db> {
for intersection in &self.intersections {
if intersection.negative.iter().any(|negative| {
negative
.into_enum_literal()
.as_enum_literal()
.is_some_and(|lit| lit.enum_class_instance(self.db) == ty)
}) {
contains_enum_literal_as_negative_element = true;

View file

@ -378,7 +378,7 @@ impl<'db> Bindings<'db> {
..,
] if property.getter(db).is_some_and(|getter| {
getter
.into_function_literal()
.as_function_literal()
.is_some_and(|f| f.name(db) == "__name__")
}) =>
{
@ -392,7 +392,7 @@ impl<'db> Bindings<'db> {
] => {
match property
.getter(db)
.and_then(Type::into_function_literal)
.and_then(Type::as_function_literal)
.map(|f| f.name(db).as_str())
{
Some("__name__") => {
@ -785,7 +785,7 @@ impl<'db> Bindings<'db> {
// 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.
overload.set_return_type(Type::BooleanLiteral(
ty.into_class_literal()
ty.as_class_literal()
.is_some_and(|class| class.is_protocol(db)),
));
}
@ -817,7 +817,7 @@ impl<'db> Bindings<'db> {
continue;
};
let Some(attr_name) = attr_name.into_string_literal() else {
let Some(attr_name) = attr_name.as_string_literal() else {
continue;
};

View file

@ -1724,7 +1724,7 @@ impl<'db> ClassLiteral<'db> {
/// Determine if this is an abstract class.
pub(super) fn is_abstract(self, db: &'db dyn Db) -> bool {
self.metaclass(db)
.into_class_literal()
.as_class_literal()
.is_some_and(|metaclass| metaclass.is_known(db, KnownClass::ABCMeta))
}
@ -1758,7 +1758,7 @@ impl<'db> ClassLiteral<'db> {
) -> impl Iterator<Item = KnownFunction> + 'db {
self.decorators(db)
.iter()
.filter_map(|deco| deco.into_function_literal())
.filter_map(|deco| deco.as_function_literal())
.filter_map(|decorator| decorator.known(db))
}
@ -2398,7 +2398,7 @@ impl<'db> ClassLiteral<'db> {
(CodeGeneratorKind::NamedTuple, name) if name != "__init__" => {
KnownClass::NamedTupleFallback
.to_class_literal(db)
.into_class_literal()?
.as_class_literal()?
.own_class_member(db, self.inherited_generic_context(db), None, name)
.ignore_possibly_unbound()
.map(|ty| {
@ -5250,7 +5250,7 @@ impl KnownClass {
};
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;
};
let Some(name) = name.into_string_literal() else {
let Some(name) = name.as_string_literal() else {
if let Some(builder) =
context.report_lint(&INVALID_TYPE_ALIAS_TYPE, call_expression)
{

View file

@ -192,7 +192,7 @@ impl<'db, 'ast> InferContext<'db, 'ast> {
.ancestor_scopes(scope_id)
.filter_map(|(_, scope)| scope.node().as_function())
.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`.
function_scope_tys.any(|function_ty| {

View file

@ -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 {
// 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>).
mode.into_string_literal().is_none_or(|mode| {
mode.as_string_literal().is_none_or(|mode| {
!matches!(
mode.value(db),
"r+" | "+r"
@ -1557,7 +1557,7 @@ impl KnownFunction {
return;
}
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))
{
builder.into_diagnostic(format_args!("Static assertion error: {message}"))

View file

@ -35,7 +35,7 @@ pub(crate) fn enclosing_generic_contexts<'db>(
NodeWithScopeKind::Class(class) => {
let definition = index.expect_single_definition(class);
binding_type(db, definition)
.into_class_literal()?
.as_class_literal()?
.generic_context(db)
}
NodeWithScopeKind::Function(function) => {
@ -43,15 +43,15 @@ pub(crate) fn enclosing_generic_contexts<'db>(
infer_definition_types(db, definition)
.undecorated_type()
.expect("function should have undecorated type")
.into_function_literal()?
.as_function_literal()?
.last_definition_signature(db)
.generic_context
}
NodeWithScopeKind::TypeAlias(type_alias) => {
let definition = index.expect_single_definition(type_alias);
binding_type(db, definition)
.into_type_alias()?
.into_pep_695_type_alias()?
.as_type_alias()?
.as_pep_695_type_alias()?
.generic_context(db)
}
_ => None,
@ -1284,7 +1284,7 @@ impl<'db> SpecializationBuilder<'db> {
let types_have_typevars = formal_union
.elements(self.db)
.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()
else {
return Ok(());
@ -1305,7 +1305,7 @@ impl<'db> SpecializationBuilder<'db> {
// type. (Note that we've already handled above the case where the actual is
// assignable to any _non-typevar_ union element.)
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() {
self.add_type_mapping(bound_typevar, actual);
}

View file

@ -777,7 +777,7 @@ pub fn definitions_for_keyword_argument<'db>(
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);
// 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);
// 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 =
CallArguments::from_arguments(&call_expr.arguments, |_, splatted_value| {
splatted_value.inferred_type(model)

View file

@ -490,7 +490,7 @@ pub(crate) fn nearest_enclosing_class<'db>(
infer_definition_types(db, definition)
.declaration_type(definition)
.inner_type()
.into_class_literal()
.as_class_literal()
})
}
@ -514,7 +514,7 @@ pub(crate) fn nearest_enclosing_function<'db>(
inference
.undecorated_type()
.unwrap_or_else(|| inference.declaration_type(definition).inner_type())
.into_function_literal()
.as_function_literal()
})
}

View file

@ -531,7 +531,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
// Filter out class literals that result from imports
if let DefinitionKind::Class(class) = definition.kind(self.db()) {
ty.inner_type()
.into_class_literal()
.as_class_literal()
.map(|class_literal| (class_literal, class.node(self.module())))
} else {
None
@ -939,7 +939,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
if !matches!(definition.kind(self.db()), DefinitionKind::Function(_)) {
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) {
Some(definition.place(self.db()))
} else {
@ -2200,12 +2200,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
{
Ok(return_ty) => {
let is_input_function_like = inferred_ty
.into_callable(self.db())
.and_then(Type::unwrap_as_callable_type)
.try_upcast_to_callable(self.db())
.and_then(Type::as_callable)
.is_some_and(|callable| callable.is_function_like(self.db()));
if is_input_function_like
&& let Some(callable_type) = return_ty.unwrap_as_callable_type()
{
if is_input_function_like && let Some(callable_type) = return_ty.as_callable() {
// 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
// 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 {
let decorator_ty = self.infer_decorator(decorator);
if decorator_ty
.into_function_literal()
.as_function_literal()
.is_some_and(|function| function.is_known(self.db(), KnownFunction::Dataclass))
{
dataclass_params = Some(DataclassParams::default());
@ -3342,8 +3340,8 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
let assigned_d = assigned_ty.display(db);
let value_d = value_ty.display(db);
if let Some(typed_dict) = value_ty.into_typed_dict() {
if let Some(key) = slice_ty.into_string_literal() {
if let Some(typed_dict) = value_ty.as_typed_dict() {
if let Some(key) = slice_ty.as_string_literal() {
let key = key.value(self.db());
validate_typed_dict_key_assignment(
&self.context,
@ -4056,7 +4054,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
);
let typevar_class = callable_type
.into_class_literal()
.as_class_literal()
.and_then(|cls| cls.known(self.db()))
.filter(|cls| {
matches!(cls, KnownClass::TypeVar | KnownClass::ExtensionsTypeVar)
@ -4278,10 +4276,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
);
};
let Some(name_param) = name_param_ty
.into_string_literal()
.map(|name| name.value(db))
else {
let Some(name_param) = name_param_ty.as_string_literal().map(|name| name.value(db)) else {
return error(
&self.context,
"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
// (e.g. `from parent import submodule` inside the `parent` module).
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()));
// First try loading the requested attribute from the module.
@ -5871,7 +5866,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
} = dict;
// 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)
{
return ty;
@ -6595,10 +6590,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
self.infer_all_argument_types(arguments, &mut call_arguments, &bindings);
// 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()) {
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(
&self.context,
typed_dict,
@ -9459,7 +9454,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
}
}
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();
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
if !value_ty
.into_class_literal()
.as_class_literal()
.is_some_and(|class| class.iter_mro(db, None).contains(&ClassBase::Generic))
{
report_non_subscriptable(context, value_node.into(), value_ty, "__class_getitem__");

View file

@ -1157,7 +1157,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
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
.context
.report_lint(&INVALID_TYPE_FORM, arguments_slice)

View file

@ -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
// `Q`'s members in a Liskov-incompatible way.
let type_to_test = self
.into_protocol_instance()
.as_protocol_instance()
.and_then(ProtocolInstanceType::as_nominal_type)
.map(Type::NominalInstance)
.unwrap_or(self);

View file

@ -634,7 +634,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
// Add the narrowed values from the RHS first, to keep literals before broader types.
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) {
// Keep only the non-single-valued portion of the original type.
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 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) {
if element.is_single_valued(self.db)
|| element.is_literal_string()
@ -840,7 +840,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
let callable_type = inference.expression_type(&**callable);
if callable_type
.into_class_literal()
.as_class_literal()
.is_some_and(|c| c.is_known(self.db, KnownClass::Type))
{
let place = self.expect_place(&target);
@ -903,7 +903,7 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
if function == KnownFunction::HasAttr {
let attr = inference
.expression_type(second_arg)
.into_string_literal()?
.as_string_literal()?
.value(self.db);
if !is_identifier(attr) {

View file

@ -641,7 +641,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
// unfortunately not sufficient to obtain the `Callable` supertypes of these types, due to the
// complex interaction between `__new__`, `__init__` and metaclass `__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);
};
attribute_type

View file

@ -55,7 +55,7 @@ fn infer_method_information<'db>(
let method = infer_definition_types(db, definition)
.declaration_type(definition)
.inner_type()
.into_function_literal()?;
.as_function_literal()?;
let class_def = index.expect_single_definition(class_node);
let (class_literal, class_is_generic) = match infer_definition_types(db, class_def)