From f73bb45be681a17b90fb6239b47b054d2c8b026b Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 14 Oct 2025 09:53:29 +0200 Subject: [PATCH] [ty] Rename Type unwrapping methods (#20857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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>`. ## Test Plan Pure refactoring --- crates/ty_python_semantic/src/place.rs | 2 +- .../reachability_constraints.rs | 2 +- crates/ty_python_semantic/src/types.rs | 63 +++++++++---------- .../ty_python_semantic/src/types/builder.rs | 4 +- .../ty_python_semantic/src/types/call/bind.rs | 8 +-- crates/ty_python_semantic/src/types/class.rs | 10 +-- .../ty_python_semantic/src/types/context.rs | 2 +- .../ty_python_semantic/src/types/function.rs | 4 +- .../ty_python_semantic/src/types/generics.rs | 12 ++-- .../src/types/ide_support.rs | 4 +- crates/ty_python_semantic/src/types/infer.rs | 4 +- .../src/types/infer/builder.rs | 37 +++++------ .../types/infer/builder/type_expression.rs | 2 +- .../ty_python_semantic/src/types/instance.rs | 2 +- crates/ty_python_semantic/src/types/narrow.rs | 8 +-- .../src/types/protocol_class.rs | 2 +- .../src/types/signatures.rs | 2 +- 17 files changed, 81 insertions(+), 87 deletions(-) diff --git a/crates/ty_python_semantic/src/place.rs b/crates/ty_python_semantic/src/place.rs index 7e8820cb77..6423ccc7e7 100644 --- a/crates/ty_python_semantic/src/place.rs +++ b/crates/ty_python_semantic/src/place.rs @@ -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 diff --git a/crates/ty_python_semantic/src/semantic_index/reachability_constraints.rs b/crates/ty_python_semantic/src/semantic_index/reachability_constraints.rs index 2ef1fe4c6a..67b266b3ff 100644 --- a/crates/ty_python_semantic/src/semantic_index/reachability_constraints.rs +++ b/crates/ty_python_semantic/src/semantic_index/reachability_constraints.rs @@ -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); diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 7ca7c2a44a..32bcc7aa63 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -982,39 +982,39 @@ impl<'db> Type<'db> { matches!(self, Type::TypeVar(_)) } - pub(crate) const fn into_type_var(self) -> Option> { + pub(crate) const fn as_typevar(self) -> Option> { 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> { + pub(crate) const fn as_class_literal(self) -> Option> { match self { Type::ClassLiteral(class_type) => Some(class_type), _ => None, } } - pub(crate) const fn into_type_alias(self) -> Option> { + pub(crate) const fn as_type_alias(self) -> Option> { match self { Type::KnownInstance(KnownInstanceType::TypeAliasType(type_alias)) => Some(type_alias), _ => None, } } - pub(crate) const fn into_dynamic(self) -> Option> { + pub(crate) const fn as_dynamic(self) -> Option> { match self { Type::Dynamic(dynamic_type) => Some(dynamic_type), _ => None, } } - pub(crate) const fn unwrap_as_callable_type(self) -> Option> { + pub(crate) const fn as_callable(self) -> Option> { 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> { + pub(crate) const fn as_protocol_instance(self) -> Option> { 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> { + pub(crate) fn as_enum_literal(self) -> Option> { 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> { + pub(crate) fn as_typed_dict(self) -> Option> { 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> { + pub(crate) const fn as_module_literal(self) -> Option> { match self { Type::ModuleLiteral(module) => Some(module), _ => None, } } - pub(crate) const fn into_union(self) -> Option> { + pub(crate) const fn as_union(self) -> Option> { 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> { + pub(crate) const fn as_function_literal(self) -> Option> { 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> { + pub(crate) fn as_string_literal(self) -> Option> { 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> { + pub(crate) fn try_upcast_to_callable(self, db: &'db dyn Db) -> Option> { 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> { + pub(crate) fn as_pep_695_type_alias(self) -> Option> { match self { TypeAliasType::PEP695(type_alias) => Some(type_alias), TypeAliasType::ManualPEP695(_) => None, diff --git a/crates/ty_python_semantic/src/types/builder.rs b/crates/ty_python_semantic/src/types/builder.rs index 9d101c40b2..28d589b5ae 100644 --- a/crates/ty_python_semantic/src/types/builder.rs +++ b/crates/ty_python_semantic/src/types/builder.rs @@ -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::>(); @@ -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; diff --git a/crates/ty_python_semantic/src/types/call/bind.rs b/crates/ty_python_semantic/src/types/call/bind.rs index 7854982a73..b1b1b074aa 100644 --- a/crates/ty_python_semantic/src/types/call/bind.rs +++ b/crates/ty_python_semantic/src/types/call/bind.rs @@ -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; }; diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index 201e382fdd..01647b1c01 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -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 + '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) { diff --git a/crates/ty_python_semantic/src/types/context.rs b/crates/ty_python_semantic/src/types/context.rs index d4ac8fd898..2221ced32d 100644 --- a/crates/ty_python_semantic/src/types/context.rs +++ b/crates/ty_python_semantic/src/types/context.rs @@ -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| { diff --git a/crates/ty_python_semantic/src/types/function.rs b/crates/ty_python_semantic/src/types/function.rs index f7cce4e03a..b6867b84ea 100644 --- a/crates/ty_python_semantic/src/types/function.rs +++ b/crates/ty_python_semantic/src/types/function.rs @@ -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 (). - 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}")) diff --git a/crates/ty_python_semantic/src/types/generics.rs b/crates/ty_python_semantic/src/types/generics.rs index afb3cc45ce..68b4d2a95c 100644 --- a/crates/ty_python_semantic/src/types/generics.rs +++ b/crates/ty_python_semantic/src/types/generics.rs @@ -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); } diff --git a/crates/ty_python_semantic/src/types/ide_support.rs b/crates/ty_python_semantic/src/types/ide_support.rs index 1b00a41007..a5fe27877c 100644 --- a/crates/ty_python_semantic/src/types/ide_support.rs +++ b/crates/ty_python_semantic/src/types/ide_support.rs @@ -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) diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index 3d949a395a..171fa42438 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -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() }) } diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index 538d170ae6..b09b3f0196 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -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__"); diff --git a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs index a04f690338..e4a4948b62 100644 --- a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs +++ b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs @@ -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) diff --git a/crates/ty_python_semantic/src/types/instance.rs b/crates/ty_python_semantic/src/types/instance.rs index a7515898d1..9079536435 100644 --- a/crates/ty_python_semantic/src/types/instance.rs +++ b/crates/ty_python_semantic/src/types/instance.rs @@ -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); diff --git a/crates/ty_python_semantic/src/types/narrow.rs b/crates/ty_python_semantic/src/types/narrow.rs index 2fb6157acb..20d505bcab 100644 --- a/crates/ty_python_semantic/src/types/narrow.rs +++ b/crates/ty_python_semantic/src/types/narrow.rs @@ -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) { diff --git a/crates/ty_python_semantic/src/types/protocol_class.rs b/crates/ty_python_semantic/src/types/protocol_class.rs index 529824b1ea..716b814aaa 100644 --- a/crates/ty_python_semantic/src/types/protocol_class.rs +++ b/crates/ty_python_semantic/src/types/protocol_class.rs @@ -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 diff --git a/crates/ty_python_semantic/src/types/signatures.rs b/crates/ty_python_semantic/src/types/signatures.rs index 8547d41a8e..ed96430b48 100644 --- a/crates/ty_python_semantic/src/types/signatures.rs +++ b/crates/ty_python_semantic/src/types/signatures.rs @@ -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)