@@ -355,7 +355,7 @@ def has_no_attr(
355
355
member : str ,
356
356
context : Context ,
357
357
module_symbol_table : SymbolTable | None = None ,
358
- ) -> Type :
358
+ ) -> ErrorCode | None :
359
359
"""Report a missing or non-accessible member.
360
360
361
361
original_type is the top-level type on which the error occurred.
@@ -370,44 +370,49 @@ def has_no_attr(
370
370
directly available on original_type
371
371
372
372
If member corresponds to an operator, use the corresponding operator
373
- name in the messages. Return type Any .
373
+ name in the messages. Return the error code that was produced, if any .
374
374
"""
375
375
original_type = get_proper_type (original_type )
376
376
typ = get_proper_type (typ )
377
377
378
378
if isinstance (original_type , Instance ) and original_type .type .has_readable_member (member ):
379
379
self .fail (f'Member "{ member } " is not assignable' , context )
380
+ return None
380
381
elif member == "__contains__" :
381
382
self .fail (
382
383
f"Unsupported right operand type for in ({ format_type (original_type , self .options )} )" ,
383
384
context ,
384
385
code = codes .OPERATOR ,
385
386
)
387
+ return codes .OPERATOR
386
388
elif member in op_methods .values ():
387
389
# Access to a binary operator member (e.g. _add). This case does
388
390
# not handle indexing operations.
389
391
for op , method in op_methods .items ():
390
392
if method == member :
391
393
self .unsupported_left_operand (op , original_type , context )
392
- break
394
+ return codes . OPERATOR
393
395
elif member == "__neg__" :
394
396
self .fail (
395
397
f"Unsupported operand type for unary - ({ format_type (original_type , self .options )} )" ,
396
398
context ,
397
399
code = codes .OPERATOR ,
398
400
)
401
+ return codes .OPERATOR
399
402
elif member == "__pos__" :
400
403
self .fail (
401
404
f"Unsupported operand type for unary + ({ format_type (original_type , self .options )} )" ,
402
405
context ,
403
406
code = codes .OPERATOR ,
404
407
)
408
+ return codes .OPERATOR
405
409
elif member == "__invert__" :
406
410
self .fail (
407
411
f"Unsupported operand type for ~ ({ format_type (original_type , self .options )} )" ,
408
412
context ,
409
413
code = codes .OPERATOR ,
410
414
)
415
+ return codes .OPERATOR
411
416
elif member == "__getitem__" :
412
417
# Indexed get.
413
418
# TODO: Fix this consistently in format_type
@@ -418,12 +423,14 @@ def has_no_attr(
418
423
),
419
424
context ,
420
425
)
426
+ return None
421
427
else :
422
428
self .fail (
423
429
f"Value of type { format_type (original_type , self .options )} is not indexable" ,
424
430
context ,
425
431
code = codes .INDEX ,
426
432
)
433
+ return codes .INDEX
427
434
elif member == "__setitem__" :
428
435
# Indexed set.
429
436
self .fail (
@@ -433,19 +440,22 @@ def has_no_attr(
433
440
context ,
434
441
code = codes .INDEX ,
435
442
)
443
+ return codes .INDEX
436
444
elif member == "__call__" :
437
445
if isinstance (original_type , Instance ) and (
438
446
original_type .type .fullname == "builtins.function"
439
447
):
440
448
# "'function' not callable" is a confusing error message.
441
449
# Explain that the problem is that the type of the function is not known.
442
450
self .fail ("Cannot call function of unknown type" , context , code = codes .OPERATOR )
451
+ return codes .OPERATOR
443
452
else :
444
453
self .fail (
445
454
message_registry .NOT_CALLABLE .format (format_type (original_type , self .options )),
446
455
context ,
447
456
code = codes .OPERATOR ,
448
457
)
458
+ return codes .OPERATOR
449
459
else :
450
460
# The non-special case: a missing ordinary attribute.
451
461
extra = ""
@@ -501,6 +511,7 @@ def has_no_attr(
501
511
context ,
502
512
code = codes .ATTR_DEFINED ,
503
513
)
514
+ return codes .ATTR_DEFINED
504
515
elif isinstance (original_type , UnionType ):
505
516
# The checker passes "object" in lieu of "None" for attribute
506
517
# checks, so we manually convert it back.
@@ -518,6 +529,7 @@ def has_no_attr(
518
529
context ,
519
530
code = codes .UNION_ATTR ,
520
531
)
532
+ return codes .UNION_ATTR
521
533
elif isinstance (original_type , TypeVarType ):
522
534
bound = get_proper_type (original_type .upper_bound )
523
535
if isinstance (bound , UnionType ):
@@ -531,6 +543,7 @@ def has_no_attr(
531
543
context ,
532
544
code = codes .UNION_ATTR ,
533
545
)
546
+ return codes .UNION_ATTR
534
547
else :
535
548
self .fail (
536
549
'{} has no attribute "{}"{}' .format (
@@ -539,7 +552,8 @@ def has_no_attr(
539
552
context ,
540
553
code = codes .ATTR_DEFINED ,
541
554
)
542
- return AnyType (TypeOfAny .from_error )
555
+ return codes .ATTR_DEFINED
556
+ return None
543
557
544
558
def unsupported_operand_types (
545
559
self ,
@@ -1107,8 +1121,8 @@ def unpacking_strings_disallowed(self, context: Context) -> None:
1107
1121
def type_not_iterable (self , type : Type , context : Context ) -> None :
1108
1122
self .fail (f"{ format_type (type , self .options )} object is not iterable" , context )
1109
1123
1110
- def possible_missing_await (self , context : Context ) -> None :
1111
- self .note ('Maybe you forgot to use "await"?' , context )
1124
+ def possible_missing_await (self , context : Context , code : ErrorCode | None ) -> None :
1125
+ self .note ('Maybe you forgot to use "await"?' , context , code = code )
1112
1126
1113
1127
def incompatible_operator_assignment (self , op : str , context : Context ) -> None :
1114
1128
self .fail (f"Result type of { op } incompatible in assignment" , context )
0 commit comments