@@ -1596,7 +1596,10 @@ impl<'db> ClassLiteral<'db> {
15961596
15971597 let field_policy = CodeGeneratorKind :: from_class ( db, self ) ?;
15981598
1599- let signature_from_fields = |mut parameters : Vec < _ > | {
1599+ let instance_ty =
1600+ Type :: instance ( db, self . apply_optional_specialization ( db, specialization) ) ;
1601+
1602+ let signature_from_fields = |mut parameters : Vec < _ > , return_ty : Option < Type < ' db > > | {
16001603 let mut kw_only_field_seen = false ;
16011604 for (
16021605 field_name,
@@ -1669,21 +1672,27 @@ impl<'db> ClassLiteral<'db> {
16691672 }
16701673 }
16711674
1672- let mut parameter = if kw_only_field_seen {
1675+ // For the `__replace__` signature, force to kw only
1676+ let mut parameter = if kw_only_field_seen || name == "__replace__" {
16731677 Parameter :: keyword_only ( field_name)
16741678 } else {
16751679 Parameter :: positional_or_keyword ( field_name)
16761680 }
16771681 . with_annotated_type ( field_ty) ;
16781682
1679- if let Some ( default_ty) = default_ty {
1683+ if name == "__replace__" {
1684+ // When replacing, we know there is a default value for the field
1685+ // (the value that is currently assigned to the field)
1686+ // assume this to be the declared type of the field
1687+ parameter = parameter. with_default_type ( field_ty) ;
1688+ } else if let Some ( default_ty) = default_ty {
16801689 parameter = parameter. with_default_type ( default_ty) ;
16811690 }
16821691
16831692 parameters. push ( parameter) ;
16841693 }
16851694
1686- let mut signature = Signature :: new ( Parameters :: new ( parameters) , Some ( Type :: none ( db ) ) ) ;
1695+ let mut signature = Signature :: new ( Parameters :: new ( parameters) , return_ty ) ;
16871696 signature. inherited_generic_context = self . generic_context ( db) ;
16881697 Some ( CallableType :: function_like ( db, signature) )
16891698 } ;
@@ -1701,16 +1710,13 @@ impl<'db> ClassLiteral<'db> {
17011710
17021711 let self_parameter = Parameter :: positional_or_keyword ( Name :: new_static ( "self" ) )
17031712 // TODO: could be `Self`.
1704- . with_annotated_type ( Type :: instance (
1705- db,
1706- self . apply_optional_specialization ( db, specialization) ,
1707- ) ) ;
1708- signature_from_fields ( vec ! [ self_parameter] )
1713+ . with_annotated_type ( instance_ty) ;
1714+ signature_from_fields ( vec ! [ self_parameter] , Some ( Type :: none ( db) ) )
17091715 }
17101716 ( CodeGeneratorKind :: NamedTuple , "__new__" ) => {
17111717 let cls_parameter = Parameter :: positional_or_keyword ( Name :: new_static ( "cls" ) )
17121718 . with_annotated_type ( KnownClass :: Type . to_instance ( db) ) ;
1713- signature_from_fields ( vec ! [ cls_parameter] )
1719+ signature_from_fields ( vec ! [ cls_parameter] , Some ( Type :: none ( db ) ) )
17141720 }
17151721 ( CodeGeneratorKind :: DataclassLike , "__lt__" | "__le__" | "__gt__" | "__ge__" ) => {
17161722 if !has_dataclass_param ( DataclassParams :: ORDER ) {
@@ -1721,16 +1727,10 @@ impl<'db> ClassLiteral<'db> {
17211727 Parameters :: new ( [
17221728 Parameter :: positional_or_keyword ( Name :: new_static ( "self" ) )
17231729 // TODO: could be `Self`.
1724- . with_annotated_type ( Type :: instance (
1725- db,
1726- self . apply_optional_specialization ( db, specialization) ,
1727- ) ) ,
1730+ . with_annotated_type ( instance_ty) ,
17281731 Parameter :: positional_or_keyword ( Name :: new_static ( "other" ) )
17291732 // TODO: could be `Self`.
1730- . with_annotated_type ( Type :: instance (
1731- db,
1732- self . apply_optional_specialization ( db, specialization) ,
1733- ) ) ,
1733+ . with_annotated_type ( instance_ty) ,
17341734 ] ) ,
17351735 Some ( KnownClass :: Bool . to_instance ( db) ) ,
17361736 ) ;
@@ -1745,15 +1745,20 @@ impl<'db> ClassLiteral<'db> {
17451745 . place
17461746 . ignore_possibly_unbound ( )
17471747 }
1748+ ( CodeGeneratorKind :: DataclassLike , "__replace__" )
1749+ if Program :: get ( db) . python_version ( db) >= PythonVersion :: PY313 =>
1750+ {
1751+ let self_parameter = Parameter :: positional_or_keyword ( Name :: new_static ( "self" ) )
1752+ . with_annotated_type ( instance_ty) ;
1753+
1754+ signature_from_fields ( vec ! [ self_parameter] , Some ( instance_ty) )
1755+ }
17481756 ( CodeGeneratorKind :: DataclassLike , "__setattr__" ) => {
17491757 if has_dataclass_param ( DataclassParams :: FROZEN ) {
17501758 let signature = Signature :: new (
17511759 Parameters :: new ( [
17521760 Parameter :: positional_or_keyword ( Name :: new_static ( "self" ) )
1753- . with_annotated_type ( Type :: instance (
1754- db,
1755- self . apply_optional_specialization ( db, specialization) ,
1756- ) ) ,
1761+ . with_annotated_type ( instance_ty) ,
17571762 Parameter :: positional_or_keyword ( Name :: new_static ( "name" ) ) ,
17581763 Parameter :: positional_or_keyword ( Name :: new_static ( "value" ) ) ,
17591764 ] ) ,
0 commit comments