@@ -177,6 +177,9 @@ class ExpressionChecker(ExpressionVisitor[Type]):
177177 # Type context for type inference
178178 type_context : List [Optional [Type ]]
179179
180+ # cache resolved types in some cases
181+ resolved_type : Dict [Expression , ProperType ]
182+
180183 strfrm_checker : StringFormatterChecker
181184 plugin : Plugin
182185
@@ -197,6 +200,11 @@ def __init__(self,
197200 self .type_overrides : Dict [Expression , Type ] = {}
198201 self .strfrm_checker = StringFormatterChecker (self , self .chk , self .msg )
199202
203+ self .resolved_type = {}
204+
205+ def reset (self ) -> None :
206+ self .resolved_type = {}
207+
200208 def visit_name_expr (self , e : NameExpr ) -> Type :
201209 """Type check a name expression.
202210
@@ -3269,13 +3277,13 @@ def apply_type_arguments_to_callable(
32693277
32703278 def visit_list_expr (self , e : ListExpr ) -> Type :
32713279 """Type check a list expression [...]."""
3272- return self .check_lst_expr (e . items , 'builtins.list' , '<list>' , e )
3280+ return self .check_lst_expr (e , 'builtins.list' , '<list>' )
32733281
32743282 def visit_set_expr (self , e : SetExpr ) -> Type :
3275- return self .check_lst_expr (e . items , 'builtins.set' , '<set>' , e )
3283+ return self .check_lst_expr (e , 'builtins.set' , '<set>' )
32763284
32773285 def fast_container_type (
3278- self , items : List [ Expression ], container_fullname : str
3286+ self , e : Union [ ListExpr , SetExpr , TupleExpr ], container_fullname : str
32793287 ) -> Optional [Type ]:
32803288 """
32813289 Fast path to determine the type of a list or set literal,
@@ -3290,21 +3298,28 @@ def fast_container_type(
32903298 ctx = self .type_context [- 1 ]
32913299 if ctx :
32923300 return None
3301+ rt = self .resolved_type .get (e , None )
3302+ if rt is not None :
3303+ return rt if isinstance (rt , Instance ) else None
32933304 values : List [Type ] = []
3294- for item in items :
3305+ for item in e . items :
32953306 if isinstance (item , StarExpr ):
32963307 # fallback to slow path
3308+ self .resolved_type [e ] = NoneType ()
32973309 return None
32983310 values .append (self .accept (item ))
32993311 vt = join .join_type_list (values )
33003312 if not allow_fast_container_literal (vt ):
3313+ self .resolved_type [e ] = NoneType ()
33013314 return None
3302- return self .chk .named_generic_type (container_fullname , [vt ])
3315+ ct = self .chk .named_generic_type (container_fullname , [vt ])
3316+ self .resolved_type [e ] = ct
3317+ return ct
33033318
3304- def check_lst_expr (self , items : List [ Expression ], fullname : str ,
3305- tag : str , context : Context ) -> Type :
3319+ def check_lst_expr (self , e : Union [ ListExpr , SetExpr , TupleExpr ], fullname : str ,
3320+ tag : str ) -> Type :
33063321 # fast path
3307- t = self .fast_container_type (items , fullname )
3322+ t = self .fast_container_type (e , fullname )
33083323 if t :
33093324 return t
33103325
@@ -3323,10 +3338,10 @@ def check_lst_expr(self, items: List[Expression], fullname: str,
33233338 variables = [tv ])
33243339 out = self .check_call (constructor ,
33253340 [(i .expr if isinstance (i , StarExpr ) else i )
3326- for i in items ],
3341+ for i in e . items ],
33273342 [(nodes .ARG_STAR if isinstance (i , StarExpr ) else nodes .ARG_POS )
3328- for i in items ],
3329- context )[0 ]
3343+ for i in e . items ],
3344+ e )[0 ]
33303345 return remove_instance_last_known_values (out )
33313346
33323347 def visit_tuple_expr (self , e : TupleExpr ) -> Type :
@@ -3376,7 +3391,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
33763391 else :
33773392 # A star expression that's not a Tuple.
33783393 # Treat the whole thing as a variable-length tuple.
3379- return self .check_lst_expr (e . items , 'builtins.tuple' , '<tuple>' , e )
3394+ return self .check_lst_expr (e , 'builtins.tuple' , '<tuple>' )
33803395 else :
33813396 if not type_context_items or j >= len (type_context_items ):
33823397 tt = self .accept (item )
@@ -3402,6 +3417,9 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]:
34023417 ctx = self .type_context [- 1 ]
34033418 if ctx :
34043419 return None
3420+ rt = self .resolved_type .get (e , None )
3421+ if rt is not None :
3422+ return rt if isinstance (rt , Instance ) else None
34053423 keys : List [Type ] = []
34063424 values : List [Type ] = []
34073425 stargs : Optional [Tuple [Type , Type ]] = None
@@ -3415,17 +3433,22 @@ def fast_dict_type(self, e: DictExpr) -> Optional[Type]:
34153433 ):
34163434 stargs = (st .args [0 ], st .args [1 ])
34173435 else :
3436+ self .resolved_type [e ] = NoneType ()
34183437 return None
34193438 else :
34203439 keys .append (self .accept (key ))
34213440 values .append (self .accept (value ))
34223441 kt = join .join_type_list (keys )
34233442 vt = join .join_type_list (values )
34243443 if not (allow_fast_container_literal (kt ) and allow_fast_container_literal (vt )):
3444+ self .resolved_type [e ] = NoneType ()
34253445 return None
34263446 if stargs and (stargs [0 ] != kt or stargs [1 ] != vt ):
3447+ self .resolved_type [e ] = NoneType ()
34273448 return None
3428- return self .chk .named_generic_type ('builtins.dict' , [kt , vt ])
3449+ dt = self .chk .named_generic_type ('builtins.dict' , [kt , vt ])
3450+ self .resolved_type [e ] = dt
3451+ return dt
34293452
34303453 def visit_dict_expr (self , e : DictExpr ) -> Type :
34313454 """Type check a dict expression.
0 commit comments