@@ -66,6 +66,8 @@ pub enum CallTarget {
66
66
BoundMethod ( Type , TargetWithTParams < Function > ) ,
67
67
/// A class object.
68
68
Class ( ClassType ) ,
69
+ /// A class object called via type[Self] (returns Self instead of ClassType).
70
+ SelfClass ( ClassType ) ,
69
71
/// A TypedDict.
70
72
TypedDict ( TypedDict ) ,
71
73
/// An overloaded function.
@@ -141,9 +143,12 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
141
143
Type :: ClassDef ( cls) => {
142
144
self . as_call_target_impl ( Type :: type_form ( self . instantiate ( & cls) ) , quantified)
143
145
}
144
- Type :: Type ( box Type :: ClassType ( cls) ) | Type :: Type ( box Type :: SelfType ( cls ) ) => {
146
+ Type :: Type ( box Type :: ClassType ( cls) ) => {
145
147
Some ( CallTarget :: Class ( cls) )
146
148
}
149
+ Type :: Type ( box Type :: SelfType ( cls) ) => {
150
+ Some ( CallTarget :: SelfClass ( cls) )
151
+ }
147
152
Type :: Type ( box Type :: Tuple ( tuple) ) => {
148
153
Some ( CallTarget :: Class ( self . erase_tuple_type ( tuple) ) )
149
154
}
@@ -633,6 +638,45 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
633
638
} ;
634
639
self . construct_class ( cls, args, keywords, range, errors, context, hint)
635
640
}
641
+ CallTarget :: SelfClass ( cls) => {
642
+ if cls. has_qname ( "typing" , "Any" ) {
643
+ return self . error (
644
+ errors,
645
+ range,
646
+ ErrorInfo :: new ( ErrorKind :: BadInstantiation , context) ,
647
+ format ! ( "`{}` can not be instantiated" , cls. name( ) ) ,
648
+ ) ;
649
+ }
650
+ if self
651
+ . get_metadata_for_class ( cls. class_object ( ) )
652
+ . is_protocol ( )
653
+ {
654
+ self . error (
655
+ errors,
656
+ range,
657
+ ErrorInfo :: new ( ErrorKind :: BadInstantiation , context) ,
658
+ format ! (
659
+ "Cannot instantiate `{}` because it is a protocol" ,
660
+ cls. name( )
661
+ ) ,
662
+ ) ;
663
+ }
664
+ if cls. has_qname ( "builtins" , "bool" ) {
665
+ match self . first_arg_type ( args, errors) {
666
+ None => ( ) ,
667
+ Some ( ty) => self . check_dunder_bool_is_callable ( & ty, range, errors) ,
668
+ }
669
+ } ;
670
+ // Call construct_class but wrap result in SelfType
671
+ let result = self . construct_class ( cls. clone ( ) , args, keywords, range, errors, context, hint) ;
672
+ // If construct_class returned a ClassType matching our class, convert it to SelfType
673
+ match & result {
674
+ Type :: ClassType ( result_cls) if result_cls. class_object ( ) == cls. class_object ( ) => {
675
+ Type :: SelfType ( result_cls. clone ( ) )
676
+ }
677
+ _ => result, // Keep other return types as-is (e.g., from custom __new__)
678
+ }
679
+ }
636
680
CallTarget :: TypedDict ( td) => {
637
681
self . construct_typed_dict ( td, args, keywords, range, errors, context, hint)
638
682
}
0 commit comments