@@ -913,37 +913,24 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
913913
914914 is_descriptor_get = defn .info and defn .name == "__get__"
915915
916- # Pre-extract callable types and literal fingerprints for each overload item.
917- item_sigs : list [CallableType | None ] = []
918- item_literal_fingerprints : list [LiteralFingerprint ] = []
919- for item in defn .items :
920- assert isinstance (item , Decorator )
921- sig = self .extract_callable_type (item .var .type , item )
922- item_sigs .append (sig )
923- item_literal_fingerprints .append (
924- build_literal_fingerprint (sig ) if sig is not None else {}
925- )
926-
916+ # Pre-extract callable types and literal fingerprints for each overload
917+ # item, skipping items whose signature could not be extracted.
918+ # Each entry is (original 0-based index, Decorator, sig, fingerprint).
919+ prepared_items : list [tuple [int , Decorator , CallableType , LiteralFingerprint ]] = []
927920 for i , item in enumerate (defn .items ):
928921 assert isinstance (item , Decorator )
929- sig1 = item_sigs [i ]
930- if sig1 is None :
931- continue
932-
933- for j , item2 in enumerate (defn .items [i + 1 :], i + 1 ):
934- assert isinstance (item2 , Decorator )
935- sig2 = item_sigs [j ]
936- if sig2 is None :
937- continue
922+ sig = self .extract_callable_type (item .var .type , item )
923+ if sig is not None :
924+ prepared_items .append ((i , item , sig , build_literal_fingerprint (sig )))
938925
926+ for prepared_items_i , (i , item , sig1 , literals_fingerprint1 ) in enumerate (prepared_items ):
927+ for j , item2 , sig2 , literals_fingerprint2 in prepared_items [prepared_items_i + 1 :]:
939928 if not are_argument_counts_overlapping (sig1 , sig2 ):
940929 continue
941930
942931 # If there is any argument position where both overloads
943932 # carry a LiteralType with different values they are disjoint.
944- if literal_args_are_disjoint (
945- item_literal_fingerprints [i ], item_literal_fingerprints [j ]
946- ):
933+ if literal_args_are_disjoint (literals_fingerprint1 , literals_fingerprint2 ):
947934 continue
948935
949936 if overload_can_never_match (sig1 , sig2 ):
@@ -8983,24 +8970,10 @@ def detach_callable(typ: CallableType, class_type_vars: list[TypeVarLikeType]) -
89838970# Using type(value) as part of the key means Literal[1] (int) and
89848971# Literal[True] (bool) are kept distinct even though 1 == True in Python.
89858972# A union such as Literal["a", "b"] or Literal["a"] | Literal["b"] produces
8986- # a frozenset of two entries; a plain Literal["a"] produces a singleton set.
8973+ # a frozenset of two entries; a plain Literal["a"] produces a length 1 set.
89878974LiteralFingerprint = dict [int , frozenset [tuple [type , LiteralValue ]]]
89888975
89898976
8990- def literal_args_are_disjoint (fp1 : LiteralFingerprint , fp2 : LiteralFingerprint ) -> bool :
8991- """Return True if two overloads are provably disjoint via a Literal argument.
8992-
8993- If there is any argument position where both carry only LiteralType values
8994- and those value sets are disjoint, no single call can match both overloads
8995- and the pairwise overlap check can be skipped entirely.
8996- """
8997- for idx , vals1 in fp1 .items ():
8998- vals2 = fp2 .get (idx )
8999- if vals2 is not None and vals1 .isdisjoint (vals2 ):
9000- return True
9001- return False
9002-
9003-
90048977def build_literal_fingerprint (sig : CallableType ) -> LiteralFingerprint :
90058978 """Build a LiteralFingerprint for one overload signature.
90068979
@@ -9033,6 +9006,20 @@ def build_literal_fingerprint(sig: CallableType) -> LiteralFingerprint:
90339006 return fingerprint
90349007
90359008
9009+ def literal_args_are_disjoint (fp1 : LiteralFingerprint , fp2 : LiteralFingerprint ) -> bool :
9010+ """Return True if two overloads are provably disjoint via a Literal argument.
9011+
9012+ If there is any argument position where both carry only LiteralType values
9013+ and those value sets are disjoint, no single call can match both overloads
9014+ and the pairwise overlap check can be skipped entirely.
9015+ """
9016+ for idx , vals1 in fp1 .items ():
9017+ vals2 = fp2 .get (idx )
9018+ if vals2 is not None and vals1 .isdisjoint (vals2 ):
9019+ return True
9020+ return False
9021+
9022+
90369023def overload_can_never_match (signature : CallableType , other : CallableType ) -> bool :
90379024 """Check if the 'other' method can never be matched due to 'signature'.
90389025
0 commit comments