@@ -5066,14 +5066,16 @@ def fast_container_type(
50665066 module-level constant definitions.
50675067
50685068 Limitations:
5069+
50695070 - no active type context
5071+ - at least one item
50705072 - no star expressions
50715073 - not after deferral
50725074 - either exactly one distinct type inside,
5073- or the joined type of all entries must be an Instance or Tuple type
5075+ or the joined type of all entries is an Instance or Tuple type,
50745076 """
50755077 ctx = self .type_context [- 1 ]
5076- if ctx :
5078+ if ctx or not e . items :
50775079 return None
50785080 if self .chk .current_node_deferred :
50795081 # Guarantees that all items will be Any, we'll reject it anyway.
@@ -5082,15 +5084,18 @@ def fast_container_type(
50825084 if rt is not None :
50835085 return rt if isinstance (rt , Instance ) else None
50845086 values : list [Type ] = []
5087+ # Preserve join order while avoiding O(n) lookups at every iteration
5088+ values_set : set [Type ] = set ()
50855089 for item in e .items :
50865090 if isinstance (item , StarExpr ):
50875091 # fallback to slow path
50885092 self .resolved_type [e ] = NoneType ()
50895093 return None
50905094
50915095 typ = self .accept (item )
5092- if typ not in values :
5096+ if typ not in values_set :
50935097 values .append (typ )
5098+ values_set .add (typ )
50945099
50955100 vt = self ._first_or_join_fast_item (values )
50965101 if vt is None :
@@ -5268,12 +5273,15 @@ def fast_dict_type(self, e: DictExpr) -> Type | None:
52685273 module-level constant definitions.
52695274
52705275 Limitations:
5276+
52715277 - no active type context
5278+ - at least one item
52725279 - only supported star expressions are other dict instances
5273- - the joined types of all keys and values must be Instance or Tuple types
5280+ - either exactly one distinct type (keys and values separately) inside,
5281+ or the joined type of all entries is an Instance or Tuple type
52745282 """
52755283 ctx = self .type_context [- 1 ]
5276- if ctx :
5284+ if ctx or not e . items :
52775285 return None
52785286
52795287 if self .chk .current_node_deferred :
@@ -5286,6 +5294,9 @@ def fast_dict_type(self, e: DictExpr) -> Type | None:
52865294
52875295 keys : list [Type ] = []
52885296 values : list [Type ] = []
5297+ # Preserve join order while avoiding O(n) lookups at every iteration
5298+ keys_set : set [Type ] = set ()
5299+ values_set : set [Type ] = set ()
52895300 stargs : tuple [Type , Type ] | None = None
52905301 for key , value in e .items :
52915302 if key is None :
@@ -5301,11 +5312,13 @@ def fast_dict_type(self, e: DictExpr) -> Type | None:
53015312 return None
53025313 else :
53035314 key_t = self .accept (key )
5304- if key_t not in keys :
5315+ if key_t not in keys_set :
53055316 keys .append (key_t )
5317+ keys_set .add (key_t )
53065318 value_t = self .accept (value )
5307- if value_t not in values :
5319+ if value_t not in values_set :
53085320 values .append (value_t )
5321+ values_set .add (value_t )
53095322
53105323 kt = self ._first_or_join_fast_item (keys )
53115324 if kt is None :
0 commit comments