mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 21:34:57 +00:00
[ty] Support __init_subclass__
(#20190)
## Summary `__init_subclass__` is implicitly a classmethod. closes https://github.com/astral-sh/ty/issues/1106 ## Test Plan Regression test
This commit is contained in:
parent
c71ce006c4
commit
5518c84ab3
6 changed files with 35 additions and 14 deletions
|
@ -46,7 +46,7 @@ use crate::types::diagnostic::{INVALID_AWAIT, INVALID_TYPE_FORM, UNSUPPORTED_BOO
|
|||
pub use crate::types::display::DisplaySettings;
|
||||
use crate::types::enums::{enum_metadata, is_single_member_enum};
|
||||
use crate::types::function::{
|
||||
DataclassTransformerParams, FunctionDecorators, FunctionSpans, FunctionType, KnownFunction,
|
||||
DataclassTransformerParams, FunctionSpans, FunctionType, KnownFunction,
|
||||
};
|
||||
use crate::types::generics::{
|
||||
GenericContext, PartialSpecialization, Specialization, bind_typevar, walk_generic_context,
|
||||
|
@ -8819,10 +8819,7 @@ impl<'db> BoundMethodType<'db> {
|
|||
/// a `@classmethod`, then it should be an instance of that bound-instance type.
|
||||
pub(crate) fn typing_self_type(self, db: &'db dyn Db) -> Type<'db> {
|
||||
let mut self_instance = self.self_instance(db);
|
||||
if self
|
||||
.function(db)
|
||||
.has_known_decorator(db, FunctionDecorators::CLASSMETHOD)
|
||||
{
|
||||
if self.function(db).is_classmethod(db) {
|
||||
self_instance = self_instance.to_instance(db).unwrap_or_else(Type::unknown);
|
||||
}
|
||||
self_instance
|
||||
|
|
|
@ -272,7 +272,7 @@ impl<'db> Bindings<'db> {
|
|||
for (overload_index, overload) in binding.matching_overloads_mut() {
|
||||
match binding_type {
|
||||
Type::MethodWrapper(MethodWrapperKind::FunctionTypeDunderGet(function)) => {
|
||||
if function.has_known_decorator(db, FunctionDecorators::CLASSMETHOD) {
|
||||
if function.is_classmethod(db) {
|
||||
match overload.parameter_types() {
|
||||
[_, Some(owner)] => {
|
||||
overload.set_return_type(Type::BoundMethod(
|
||||
|
@ -308,7 +308,7 @@ impl<'db> Bindings<'db> {
|
|||
if let [Some(function_ty @ Type::FunctionLiteral(function)), ..] =
|
||||
overload.parameter_types()
|
||||
{
|
||||
if function.has_known_decorator(db, FunctionDecorators::CLASSMETHOD) {
|
||||
if function.is_classmethod(db) {
|
||||
match overload.parameter_types() {
|
||||
[_, _, Some(owner)] => {
|
||||
overload.set_return_type(Type::BoundMethod(
|
||||
|
|
|
@ -1258,7 +1258,7 @@ pub(super) enum MethodDecorator {
|
|||
impl MethodDecorator {
|
||||
fn try_from_fn_type(db: &dyn Db, fn_type: FunctionType) -> Result<Self, ()> {
|
||||
match (
|
||||
fn_type.has_known_decorator(db, FunctionDecorators::CLASSMETHOD),
|
||||
fn_type.is_classmethod(db),
|
||||
fn_type.has_known_decorator(db, FunctionDecorators::STATICMETHOD),
|
||||
) {
|
||||
(true, true) => Err(()), // A method can't be static and class method at the same time.
|
||||
|
|
|
@ -721,6 +721,13 @@ impl<'db> FunctionType<'db> {
|
|||
self.literal(db).has_known_decorator(db, decorator)
|
||||
}
|
||||
|
||||
/// Returns true if this method is decorated with `@classmethod`, or if it is implicitly a
|
||||
/// classmethod.
|
||||
pub(crate) fn is_classmethod(self, db: &'db dyn Db) -> bool {
|
||||
self.has_known_decorator(db, FunctionDecorators::CLASSMETHOD)
|
||||
|| self.name(db) == "__init_subclass__"
|
||||
}
|
||||
|
||||
/// If the implementation of this function is deprecated, returns the `@warnings.deprecated`.
|
||||
///
|
||||
/// Checking if an overload is deprecated requires deeper call analysis.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue