@@ -93,11 +93,12 @@ def __init__(
93
93
original_type : Type ,
94
94
context : Context ,
95
95
chk : mypy .checker .TypeChecker ,
96
- self_type : Type | None ,
96
+ self_type : Type | None = None ,
97
97
module_symbol_table : SymbolTable | None = None ,
98
98
no_deferral : bool = False ,
99
99
is_self : bool = False ,
100
100
rvalue : Expression | None = None ,
101
+ suppress_errors : bool = False ,
101
102
) -> None :
102
103
self .is_lvalue = is_lvalue
103
104
self .is_super = is_super
@@ -113,13 +114,18 @@ def __init__(
113
114
if rvalue is not None :
114
115
assert is_lvalue
115
116
self .rvalue = rvalue
117
+ self .suppress_errors = suppress_errors
116
118
117
119
def named_type (self , name : str ) -> Instance :
118
120
return self .chk .named_type (name )
119
121
120
122
def not_ready_callback (self , name : str , context : Context ) -> None :
121
123
self .chk .handle_cannot_determine_type (name , context )
122
124
125
+ def fail (self , msg : str ) -> None :
126
+ if not self .suppress_errors :
127
+ self .msg .fail (msg , self .context )
128
+
123
129
def copy_modified (
124
130
self ,
125
131
* ,
@@ -138,6 +144,7 @@ def copy_modified(
138
144
module_symbol_table = self .module_symbol_table ,
139
145
no_deferral = self .no_deferral ,
140
146
rvalue = self .rvalue ,
147
+ suppress_errors = self .suppress_errors ,
141
148
)
142
149
if self_type is not None :
143
150
mx .self_type = self_type
@@ -165,6 +172,7 @@ def analyze_member_access(
165
172
no_deferral : bool = False ,
166
173
is_self : bool = False ,
167
174
rvalue : Expression | None = None ,
175
+ suppress_errors : bool = False ,
168
176
) -> Type :
169
177
"""Return the type of attribute 'name' of 'typ'.
170
178
@@ -191,6 +199,11 @@ def analyze_member_access(
191
199
192
200
'rvalue' can be provided optionally to infer better setter type when is_lvalue is True,
193
201
most notably this helps for descriptors with overloaded __set__() method.
202
+
203
+ 'suppress_errors' will skip any logic that is only needed to generate error messages.
204
+ Note that this more of a performance optimization, one should not rely on this to not
205
+ show any messages, as some may be show e.g. by callbacks called here,
206
+ use msg.filter_errors(), if needed.
194
207
"""
195
208
mx = MemberContext (
196
209
is_lvalue = is_lvalue ,
@@ -204,6 +217,7 @@ def analyze_member_access(
204
217
no_deferral = no_deferral ,
205
218
is_self = is_self ,
206
219
rvalue = rvalue ,
220
+ suppress_errors = suppress_errors ,
207
221
)
208
222
result = _analyze_member_access (name , typ , mx , override_info )
209
223
possible_literal = get_proper_type (result )
@@ -251,7 +265,8 @@ def _analyze_member_access(
251
265
)
252
266
return _analyze_member_access (name , typ .upper_bound , mx , override_info )
253
267
elif isinstance (typ , DeletedType ):
254
- mx .msg .deleted_as_rvalue (typ , mx .context )
268
+ if not mx .suppress_errors :
269
+ mx .msg .deleted_as_rvalue (typ , mx .context )
255
270
return AnyType (TypeOfAny .from_error )
256
271
return report_missing_attribute (mx .original_type , typ , name , mx )
257
272
@@ -280,6 +295,8 @@ def report_missing_attribute(
280
295
mx : MemberContext ,
281
296
override_info : TypeInfo | None = None ,
282
297
) -> Type :
298
+ if mx .suppress_errors :
299
+ return AnyType (TypeOfAny .from_error )
283
300
error_code = mx .msg .has_no_attr (original_type , typ , name , mx .context , mx .module_symbol_table )
284
301
if not mx .msg .prefer_simple_messages ():
285
302
if may_be_awaitable_attribute (name , typ , mx , override_info ):
@@ -297,7 +314,7 @@ def analyze_instance_member_access(
297
314
if name == "__init__" and not mx .is_super :
298
315
# Accessing __init__ in statically typed code would compromise
299
316
# type safety unless used via super().
300
- mx .msg . fail (message_registry .CANNOT_ACCESS_INIT , mx . context )
317
+ mx .fail (message_registry .CANNOT_ACCESS_INIT )
301
318
return AnyType (TypeOfAny .from_error )
302
319
303
320
# The base object has an instance type.
@@ -310,13 +327,14 @@ def analyze_instance_member_access(
310
327
state .find_occurrences
311
328
and info .name == state .find_occurrences [0 ]
312
329
and name == state .find_occurrences [1 ]
330
+ and not mx .suppress_errors
313
331
):
314
332
mx .msg .note ("Occurrence of '{}.{}'" .format (* state .find_occurrences ), mx .context )
315
333
316
334
# Look up the member. First look up the method dictionary.
317
335
method = info .get_method (name )
318
336
if method and not isinstance (method , Decorator ):
319
- if mx .is_super :
337
+ if mx .is_super and not mx . suppress_errors :
320
338
validate_super_call (method , mx )
321
339
322
340
if method .is_property :
@@ -327,7 +345,7 @@ def analyze_instance_member_access(
327
345
mx .chk .warn_deprecated (items [1 ], mx .context )
328
346
return analyze_var (name , getter .var , typ , mx )
329
347
330
- if mx .is_lvalue :
348
+ if mx .is_lvalue and not mx . suppress_errors :
331
349
mx .msg .cant_assign_to_method (mx .context )
332
350
if not isinstance (method , OverloadedFuncDef ):
333
351
signature = function_type (method , mx .named_type ("builtins.function" ))
@@ -361,7 +379,6 @@ def validate_super_call(node: FuncBase, mx: MemberContext) -> None:
361
379
unsafe_super = False
362
380
if isinstance (node , FuncDef ) and node .is_trivial_body :
363
381
unsafe_super = True
364
- impl = node
365
382
elif isinstance (node , OverloadedFuncDef ):
366
383
if node .impl :
367
384
impl = node .impl if isinstance (node .impl , FuncDef ) else node .impl .func
@@ -505,7 +522,7 @@ def analyze_member_var_access(
505
522
if isinstance (vv , Decorator ):
506
523
# The associated Var node of a decorator contains the type.
507
524
v = vv .var
508
- if mx .is_super :
525
+ if mx .is_super and not mx . suppress_errors :
509
526
validate_super_call (vv .func , mx )
510
527
511
528
if isinstance (vv , TypeInfo ):
@@ -603,7 +620,7 @@ def analyze_member_var_access(
603
620
if not itype .extra_attrs .mod_name :
604
621
return itype .extra_attrs .attrs [name ]
605
622
606
- if mx .is_super :
623
+ if mx .is_super and not mx . suppress_errors :
607
624
mx .msg .undefined_in_superclass (name , mx .context )
608
625
return AnyType (TypeOfAny .from_error )
609
626
else :
@@ -669,11 +686,10 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:
669
686
670
687
dunder_get = descriptor_type .type .get_method ("__get__" )
671
688
if dunder_get is None :
672
- mx .msg . fail (
689
+ mx .fail (
673
690
message_registry .DESCRIPTOR_GET_NOT_CALLABLE .format (
674
691
descriptor_type .str_with_options (mx .msg .options )
675
- ),
676
- mx .context ,
692
+ )
677
693
)
678
694
return AnyType (TypeOfAny .from_error )
679
695
@@ -732,11 +748,10 @@ def analyze_descriptor_access(descriptor_type: Type, mx: MemberContext) -> Type:
732
748
return inferred_dunder_get_type
733
749
734
750
if not isinstance (inferred_dunder_get_type , CallableType ):
735
- mx .msg . fail (
751
+ mx .fail (
736
752
message_registry .DESCRIPTOR_GET_NOT_CALLABLE .format (
737
753
descriptor_type .str_with_options (mx .msg .options )
738
- ),
739
- mx .context ,
754
+ )
740
755
)
741
756
return AnyType (TypeOfAny .from_error )
742
757
@@ -747,11 +762,10 @@ def analyze_descriptor_assign(descriptor_type: Instance, mx: MemberContext) -> T
747
762
instance_type = get_proper_type (mx .self_type )
748
763
dunder_set = descriptor_type .type .get_method ("__set__" )
749
764
if dunder_set is None :
750
- mx .chk . fail (
765
+ mx .fail (
751
766
message_registry .DESCRIPTOR_SET_NOT_CALLABLE .format (
752
767
descriptor_type .str_with_options (mx .msg .options )
753
- ),
754
- mx .context ,
768
+ ).value
755
769
)
756
770
return AnyType (TypeOfAny .from_error )
757
771
@@ -851,11 +865,11 @@ def analyze_var(
851
865
if typ :
852
866
if isinstance (typ , PartialType ):
853
867
return mx .chk .handle_partial_var_type (typ , mx .is_lvalue , var , mx .context )
854
- if mx .is_lvalue and var . is_property and not var . is_settable_property :
855
- # TODO allow setting attributes in subclass (although it is probably an error)
856
- mx .msg .read_only_property (name , itype .type , mx .context )
857
- if mx . is_lvalue and var .is_classvar :
858
- mx .msg .cant_assign_to_classvar (name , mx .context )
868
+ if mx .is_lvalue and not mx . suppress_errors :
869
+ if var . is_property and not var . is_settable_property :
870
+ mx .msg .read_only_property (name , itype .type , mx .context )
871
+ if var .is_classvar :
872
+ mx .msg .cant_assign_to_classvar (name , mx .context )
859
873
t = freshen_all_functions_type_vars (typ )
860
874
t = expand_self_type_if_needed (t , mx , var , original_itype )
861
875
t = expand_type_by_instance (t , itype )
@@ -875,11 +889,10 @@ def analyze_var(
875
889
call_type = typ
876
890
877
891
if isinstance (call_type , FunctionLike ) and not call_type .is_type_obj ():
878
- if mx .is_lvalue :
879
- if var .is_property :
880
- if not var .is_settable_property :
881
- mx .msg .read_only_property (name , itype .type , mx .context )
882
- else :
892
+ if mx .is_lvalue and not mx .suppress_errors :
893
+ if var .is_property and not var .is_settable_property :
894
+ mx .msg .read_only_property (name , itype .type , mx .context )
895
+ elif not var .is_property :
883
896
mx .msg .cant_assign_to_method (mx .context )
884
897
885
898
if not var .is_staticmethod :
@@ -1073,22 +1086,20 @@ def analyze_class_attribute_access(
1073
1086
1074
1087
is_decorated = isinstance (node .node , Decorator )
1075
1088
is_method = is_decorated or isinstance (node .node , FuncBase )
1076
- if mx .is_lvalue :
1089
+ if mx .is_lvalue and not mx . suppress_errors :
1077
1090
if is_method :
1078
1091
mx .msg .cant_assign_to_method (mx .context )
1079
1092
if isinstance (node .node , TypeInfo ):
1080
- mx .msg . fail (message_registry .CANNOT_ASSIGN_TO_TYPE , mx . context )
1093
+ mx .fail (message_registry .CANNOT_ASSIGN_TO_TYPE )
1081
1094
1082
1095
# Refuse class attribute access if slot defined
1083
1096
if info .slots and name in info .slots :
1084
- mx .msg . fail (message_registry .CLASS_VAR_CONFLICTS_SLOTS .format (name ), mx . context )
1097
+ mx .fail (message_registry .CLASS_VAR_CONFLICTS_SLOTS .format (name ))
1085
1098
1086
1099
# If a final attribute was declared on `self` in `__init__`, then it
1087
1100
# can't be accessed on the class object.
1088
1101
if node .implicit and isinstance (node .node , Var ) and node .node .is_final :
1089
- mx .msg .fail (
1090
- message_registry .CANNOT_ACCESS_FINAL_INSTANCE_ATTR .format (node .node .name ), mx .context
1091
- )
1102
+ mx .fail (message_registry .CANNOT_ACCESS_FINAL_INSTANCE_ATTR .format (node .node .name ))
1092
1103
1093
1104
# An assignment to final attribute on class object is also always an error,
1094
1105
# independently of types.
@@ -1146,7 +1157,7 @@ def analyze_class_attribute_access(
1146
1157
message = message_registry .GENERIC_CLASS_VAR_ACCESS
1147
1158
else :
1148
1159
message = message_registry .GENERIC_INSTANCE_VAR_CLASS_ACCESS
1149
- mx .msg . fail (message , mx . context )
1160
+ mx .fail (message )
1150
1161
t = expand_self_type_if_needed (t , mx , node .node , itype , is_class = True )
1151
1162
# Erase non-mapped variables, but keep mapped ones, even if there is an error.
1152
1163
# In the above example this means that we infer following types:
@@ -1176,9 +1187,7 @@ def analyze_class_attribute_access(
1176
1187
return AnyType (TypeOfAny .special_form )
1177
1188
1178
1189
if isinstance (node .node , TypeVarExpr ):
1179
- mx .msg .fail (
1180
- message_registry .CANNOT_USE_TYPEVAR_AS_EXPRESSION .format (info .name , name ), mx .context
1181
- )
1190
+ mx .fail (message_registry .CANNOT_USE_TYPEVAR_AS_EXPRESSION .format (info .name , name ))
1182
1191
return AnyType (TypeOfAny .from_error )
1183
1192
1184
1193
# TODO: some logic below duplicates analyze_ref_expr in checkexpr.py
@@ -1267,7 +1276,7 @@ def analyze_typeddict_access(
1267
1276
typ , mx .context .index , setitem = True
1268
1277
)
1269
1278
assigned_readonly_keys = typ .readonly_keys & key_names
1270
- if assigned_readonly_keys :
1279
+ if assigned_readonly_keys and not mx . suppress_errors :
1271
1280
mx .msg .readonly_keys_mutated (assigned_readonly_keys , context = mx .context )
1272
1281
else :
1273
1282
# It can also be `a.__setitem__(...)` direct call.
0 commit comments