@@ -586,10 +586,8 @@ impl<'db> ClassType<'db> {
586586 Place :: bound ( synthesized_dunder_method) . into ( )
587587 } ;
588588
589- let is_tuple = || class_literal. is_known ( db, KnownClass :: Tuple ) ;
590-
591589 match name {
592- "__len__" if is_tuple ( ) => {
590+ "__len__" if class_literal . is_tuple ( db ) => {
593591 let return_type = specialization
594592 . and_then ( |spec| spec. tuple ( db) . len ( ) . into_fixed_length ( ) )
595593 . and_then ( |len| i64:: try_from ( len) . ok ( ) )
@@ -599,7 +597,7 @@ impl<'db> ClassType<'db> {
599597 synthesize_simple_tuple_method ( return_type)
600598 }
601599
602- "__bool__" if is_tuple ( ) => {
600+ "__bool__" if class_literal . is_tuple ( db ) => {
603601 let return_type = specialization
604602 . map ( |spec| spec. tuple ( db) . truthiness ( ) . into_type ( db) )
605603 . unwrap_or_else ( || KnownClass :: Bool . to_instance ( db) ) ;
@@ -614,7 +612,7 @@ impl<'db> ClassType<'db> {
614612 // @overload
615613 // def __new__[T](cls: type[tuple[T, ...]], iterable: tuple[T, ...]) -> tuple[T, ...]: ...
616614 // ```
617- "__new__" if is_tuple ( ) => {
615+ "__new__" if class_literal . is_tuple ( db ) => {
618616 let mut iterable_parameter =
619617 Parameter :: positional_only ( Some ( Name :: new_static ( "iterable" ) ) ) ;
620618
@@ -727,38 +725,41 @@ impl<'db> ClassType<'db> {
727725 )
728726 . place ;
729727
730- let dunder_new_function =
731- if let Place :: Type ( Type :: FunctionLiteral ( dunder_new_function) , _) =
732- dunder_new_function_symbol
733- {
734- // Step 3: If the return type of the `__new__` evaluates to a type that is not a subclass of this class,
735- // then we should ignore the `__init__` and just return the `__new__` method.
736- let returns_non_subclass =
737- dunder_new_function
738- . signature ( db)
739- . overloads
740- . iter ( )
741- . any ( |signature| {
742- signature. return_ty . is_some_and ( |return_ty| {
743- !return_ty. is_assignable_to (
744- db,
745- self_ty
746- . to_instance ( db)
747- . expect ( "ClassType should be instantiable" ) ,
748- )
749- } )
750- } ) ;
728+ let dunder_new_signature = dunder_new_function_symbol
729+ . ignore_possibly_unbound ( )
730+ . and_then ( |ty| match ty {
731+ Type :: FunctionLiteral ( function) => Some ( function. signature ( db) ) ,
732+ Type :: Callable ( callable) => Some ( callable. signatures ( db) ) ,
733+ _ => None ,
734+ } ) ;
751735
752- let dunder_new_bound_method =
753- dunder_new_function. into_bound_method_type ( db, self_ty) ;
736+ let dunder_new_function = if let Some ( dunder_new_signature) = dunder_new_signature {
737+ // Step 3: If the return type of the `__new__` evaluates to a type that is not a subclass of this class,
738+ // then we should ignore the `__init__` and just return the `__new__` method.
739+ let returns_non_subclass = dunder_new_signature. overloads . iter ( ) . any ( |signature| {
740+ signature. return_ty . is_some_and ( |return_ty| {
741+ !return_ty. is_assignable_to (
742+ db,
743+ self_ty
744+ . to_instance ( db)
745+ . expect ( "ClassType should be instantiable" ) ,
746+ )
747+ } )
748+ } ) ;
754749
755- if returns_non_subclass {
756- return dunder_new_bound_method;
757- }
758- Some ( dunder_new_bound_method)
759- } else {
760- None
761- } ;
750+ let dunder_new_bound_method = Type :: Callable ( CallableType :: new (
751+ db,
752+ dunder_new_signature. bind_self ( ) ,
753+ true ,
754+ ) ) ;
755+
756+ if returns_non_subclass {
757+ return dunder_new_bound_method;
758+ }
759+ Some ( dunder_new_bound_method)
760+ } else {
761+ None
762+ } ;
762763
763764 let dunder_init_function_symbol = self_ty
764765 . member_lookup_with_policy (
@@ -932,6 +933,10 @@ impl<'db> ClassLiteral<'db> {
932933 self . known ( db) == Some ( known_class)
933934 }
934935
936+ pub ( crate ) fn is_tuple ( self , db : & ' db dyn Db ) -> bool {
937+ self . is_known ( db, KnownClass :: Tuple )
938+ }
939+
935940 pub ( crate ) fn generic_context ( self , db : & ' db dyn Db ) -> Option < GenericContext < ' db > > {
936941 // Several typeshed definitions examine `sys.version_info`. To break cycles, we hard-code
937942 // the knowledge that this class is not generic.
0 commit comments