@@ -1360,29 +1360,58 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
1360
1360
return TupleType (items , self .chk .named_generic_type ('builtins.tuple' , [fallback_item ]))
1361
1361
1362
1362
def visit_dict_expr (self , e : DictExpr ) -> Type :
1363
- # Translate into type checking a generic function call.
1363
+ """Type check a dict expression.
1364
+
1365
+ Translate it into a call to dict(), with provisions for **expr.
1366
+ """
1367
+ # Collect function arguments, watching out for **expr.
1368
+ args = [] # type: List[Node] # Regular "key: value"
1369
+ stargs = [] # type: List[Node] # For "**expr"
1370
+ for key , value in e .items :
1371
+ if key is None :
1372
+ stargs .append (value )
1373
+ else :
1374
+ args .append (TupleExpr ([key , value ]))
1375
+ # Define type variables (used in constructors below).
1364
1376
ktdef = TypeVarDef ('KT' , - 1 , [], self .chk .object_type ())
1365
1377
vtdef = TypeVarDef ('VT' , - 2 , [], self .chk .object_type ())
1366
1378
kt = TypeVarType (ktdef )
1367
1379
vt = TypeVarType (vtdef )
1368
- # The callable type represents a function like this:
1369
- #
1370
- # def <unnamed>(*v: Tuple[kt, vt]) -> Dict[kt, vt]: ...
1371
- constructor = CallableType (
1372
- [TupleType ([kt , vt ], self .named_type ('builtins.tuple' ))],
1373
- [nodes .ARG_STAR ],
1374
- [None ],
1375
- self .chk .named_generic_type ('builtins.dict' , [kt , vt ]),
1376
- self .named_type ('builtins.function' ),
1377
- name = '<list>' ,
1378
- variables = [ktdef , vtdef ])
1379
- # Synthesize function arguments.
1380
- args = [] # type: List[Node]
1381
- for key , value in e .items :
1382
- args .append (TupleExpr ([key , value ]))
1383
- return self .check_call (constructor ,
1384
- args ,
1385
- [nodes .ARG_POS ] * len (args ), e )[0 ]
1380
+ # Call dict(*args), unless it's empty and stargs is not.
1381
+ if args or not stargs :
1382
+ # The callable type represents a function like this:
1383
+ #
1384
+ # def <unnamed>(*v: Tuple[kt, vt]) -> Dict[kt, vt]: ...
1385
+ constructor = CallableType (
1386
+ [TupleType ([kt , vt ], self .named_type ('builtins.tuple' ))],
1387
+ [nodes .ARG_STAR ],
1388
+ [None ],
1389
+ self .chk .named_generic_type ('builtins.dict' , [kt , vt ]),
1390
+ self .named_type ('builtins.function' ),
1391
+ name = '<list>' ,
1392
+ variables = [ktdef , vtdef ])
1393
+ rv = self .check_call (constructor , args , [nodes .ARG_POS ] * len (args ), e )[0 ]
1394
+ else :
1395
+ # dict(...) will be called below.
1396
+ rv = None
1397
+ # Call rv.update(arg) for each arg in **stargs,
1398
+ # except if rv isn't set yet, then set rv = dict(arg).
1399
+ if stargs :
1400
+ for arg in stargs :
1401
+ if rv is None :
1402
+ constructor = CallableType (
1403
+ [self .chk .named_generic_type ('typing.Mapping' , [kt , vt ])],
1404
+ [nodes .ARG_POS ],
1405
+ [None ],
1406
+ self .chk .named_generic_type ('builtins.dict' , [kt , vt ]),
1407
+ self .named_type ('builtins.function' ),
1408
+ name = '<list>' ,
1409
+ variables = [ktdef , vtdef ])
1410
+ rv = self .check_call (constructor , [arg ], [nodes .ARG_POS ], arg )[0 ]
1411
+ else :
1412
+ method = self .analyze_external_member_access ('update' , rv , arg )
1413
+ self .check_call (method , [arg ], [nodes .ARG_POS ], arg )
1414
+ return rv
1386
1415
1387
1416
def visit_func_expr (self , e : FuncExpr ) -> Type :
1388
1417
"""Type check lambda expression."""
0 commit comments