@@ -166,6 +166,22 @@ def _unify(self, typea, typeb, loca, locb, makenotes=None):
166
166
loca , highlights , notes )
167
167
self .engine .process (diag )
168
168
169
+ # makenotes for the case where types of multiple elements are unified
170
+ # with the type of parent expression
171
+ def _makenotes_elts (self , elts , kind ):
172
+ def makenotes (printer , typea , typeb , loca , locb ):
173
+ return [
174
+ diagnostic .Diagnostic ("note" ,
175
+ "{kind} of type {typea}" ,
176
+ {"kind" : kind , "typea" : printer .name (elts [0 ].type )},
177
+ elts [0 ].loc ),
178
+ diagnostic .Diagnostic ("note" ,
179
+ "{kind} of type {typeb}" ,
180
+ {"kind" : kind , "typeb" : printer .name (typeb )},
181
+ locb )
182
+ ]
183
+ return makenotes
184
+
169
185
def _find_name (self , name , loc ):
170
186
for typing_env in reversed (self .env_stack ):
171
187
if name in typing_env :
@@ -212,26 +228,6 @@ def visit_FunctionDef(self, node):
212
228
213
229
return node
214
230
215
- def visit_Return (self , node ):
216
- node = self .generic_visit (node )
217
- def makenotes (printer , typea , typeb , loca , locb ):
218
- return [
219
- diagnostic .Diagnostic ("note" ,
220
- "function with return type {typea}" ,
221
- {"typea" : printer .name (typea )},
222
- self .function .name_loc ),
223
- diagnostic .Diagnostic ("note" ,
224
- "a statement returning {typeb}" ,
225
- {"typeb" : printer .name (typeb )},
226
- node .loc )
227
- ]
228
- if node .value is None :
229
- self ._unify (self .function .return_type , types .TNone (),
230
- self .function .name_loc , node .loc , makenotes )
231
- else :
232
- self ._unify (self .function .return_type , node .value .type ,
233
- self .function .name_loc , node .value .loc , makenotes )
234
-
235
231
def visit_Num (self , node ):
236
232
if isinstance (node .n , int ):
237
233
typ = types .TInt ()
@@ -265,63 +261,55 @@ def visit_List(self, node):
265
261
node = self .generic_visit (node )
266
262
node = asttyped .ListT (type = types .TList (),
267
263
elts = node .elts , ctx = node .ctx , loc = node .loc )
268
- def makenotes (printer , typea , typeb , loca , locb ):
269
- return [
270
- diagnostic .Diagnostic ("note" ,
271
- "a list element of type {typea}" ,
272
- {"typea" : printer .name (node .elts [0 ].type )},
273
- node .elts [0 ].loc ),
274
- diagnostic .Diagnostic ("note" ,
275
- "a list element of type {typeb}" ,
276
- {"typeb" : printer .name (typeb )},
277
- locb )
278
- ]
279
- for elt in node .elts :
280
- self ._unify (node .type ["elt" ], elt .type ,
281
- node .loc , elt .loc , makenotes )
282
- return node
264
+ return self .visit (node )
283
265
284
266
def visit_Subscript (self , node ):
285
267
node = self .generic_visit (node )
286
268
node = asttyped .SubscriptT (type = types .TVar (),
287
269
value = node .value , slice = node .slice , ctx = node .ctx ,
288
270
loc = node .loc )
289
- # TODO: support more than just lists
290
- self ._unify (types .TList (node .type ), node .value .type ,
291
- node .loc , node .value .loc )
292
- return node
271
+ return self .visit (node )
293
272
294
273
def visit_IfExp (self , node ):
295
274
node = self .generic_visit (node )
296
- self ._unify (node .body .type , node .orelse .type ,
297
- node .body .loc , node .orelse .loc )
298
- return asttyped .IfExpT (type = node .body .type ,
275
+ node = asttyped .IfExpT (type = types .TVar (),
299
276
test = node .test , body = node .body , orelse = node .orelse ,
300
277
if_loc = node .if_loc , else_loc = node .else_loc , loc = node .loc )
278
+ return self .visit (node )
301
279
302
280
def visit_BoolOp (self , node ):
303
281
node = self .generic_visit (node )
304
282
node = asttyped .BoolOpT (type = types .TVar (),
305
283
op = node .op , values = node .values ,
306
284
op_locs = node .op_locs , loc = node .loc )
307
- def makenotes (printer , typea , typeb , loca , locb ):
308
- return [
309
- diagnostic .Diagnostic ("note" ,
310
- "an operand of type {typea}" ,
311
- {"typea" : printer .name (node .values [0 ].type )},
312
- node .values [0 ].loc ),
313
- diagnostic .Diagnostic ("note" ,
314
- "an operand of type {typeb}" ,
315
- {"typeb" : printer .name (typeb )},
316
- locb )
317
- ]
285
+ return self .visit (node )
286
+
287
+ # Visitors that just unify types
288
+ #
289
+ def visit_ListT (self , node ):
290
+ for elt in node .elts :
291
+ self ._unify (node .type ["elt" ], elt .type ,
292
+ node .loc , elt .loc , self ._makenotes_elts (node .elts , "a list element" ))
293
+ return node
294
+
295
+ def visit_SubscriptT (self , node ):
296
+ # TODO: support more than just lists
297
+ self ._unify (types .TList (node .type ), node .value .type ,
298
+ node .loc , node .value .loc )
299
+ return node
300
+
301
+ def visit_IfExpT (self , node ):
302
+ self ._unify (node .body .type , node .orelse .type ,
303
+ node .body .loc , node .orelse .loc )
304
+ node .type = node .body .type
305
+ return node
306
+
307
+ def visit_BoolOpT (self , node ):
318
308
for value in node .values :
319
309
self ._unify (node .type , value .type ,
320
- node .loc , value .loc , makenotes )
310
+ node .loc , value .loc , self . _makenotes_elts ( node . values , "an operand" ) )
321
311
return node
322
312
323
- # Visitors that just unify types
324
- #
325
313
def visit_Assign (self , node ):
326
314
node = self .generic_visit (node )
327
315
if len (node .targets ) > 1 :
@@ -345,6 +333,26 @@ def visit_For(self, node):
345
333
node .target .loc , node .iter .loc )
346
334
return node
347
335
336
+ def visit_Return (self , node ):
337
+ node = self .generic_visit (node )
338
+ def makenotes (printer , typea , typeb , loca , locb ):
339
+ return [
340
+ diagnostic .Diagnostic ("note" ,
341
+ "function with return type {typea}" ,
342
+ {"typea" : printer .name (typea )},
343
+ self .function .name_loc ),
344
+ diagnostic .Diagnostic ("note" ,
345
+ "a statement returning {typeb}" ,
346
+ {"typeb" : printer .name (typeb )},
347
+ node .loc )
348
+ ]
349
+ if node .value is None :
350
+ self ._unify (self .function .return_type , types .TNone (),
351
+ self .function .name_loc , node .loc , makenotes )
352
+ else :
353
+ self ._unify (self .function .return_type , node .value .type ,
354
+ self .function .name_loc , node .value .loc , makenotes )
355
+
348
356
# Unsupported visitors
349
357
#
350
358
def visit_unsupported (self , node ):
0 commit comments