@@ -110,6 +110,9 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
110
110
dynamic_funcs = None # type: List[bool]
111
111
# Stack of collections of variables with partial types
112
112
partial_types = None # type: List[Dict[Var, Context]]
113
+ # Vars for which partial type errors are already reported
114
+ # (to avoid logically duplicate errors with different error context).
115
+ partial_reported = None # type: Set[Var]
113
116
globals = None # type: SymbolTable
114
117
modules = None # type: Dict[str, MypyFile]
115
118
# Nodes that couldn't be checked because some types weren't available. We'll run
@@ -157,6 +160,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option
157
160
self .return_types = []
158
161
self .dynamic_funcs = []
159
162
self .partial_types = []
163
+ self .partial_reported = set ()
160
164
self .deferred_nodes = []
161
165
self .type_map = {}
162
166
self .module_refs = set ()
@@ -1681,7 +1685,7 @@ def lvalue_type_for_inference(self, lvalues: List[Lvalue], rvalue_type: TupleTyp
1681
1685
def append_types_for_inference (lvs : List [Expression ], rv_types : List [Type ]) -> None :
1682
1686
for lv , rv_type in zip (lvs , rv_types ):
1683
1687
sub_lvalue_type , index_expr , inferred = self .check_lvalue (lv )
1684
- if sub_lvalue_type :
1688
+ if sub_lvalue_type and not isinstance ( sub_lvalue_type , PartialType ) :
1685
1689
type_parameters .append (sub_lvalue_type )
1686
1690
else : # index lvalue
1687
1691
# TODO Figure out more precise type context, probably
@@ -1692,7 +1696,7 @@ def append_types_for_inference(lvs: List[Expression], rv_types: List[Type]) -> N
1692
1696
1693
1697
if star_lv :
1694
1698
sub_lvalue_type , index_expr , inferred = self .check_lvalue (star_lv .expr )
1695
- if sub_lvalue_type :
1699
+ if sub_lvalue_type and not isinstance ( sub_lvalue_type , PartialType ) :
1696
1700
type_parameters .extend ([sub_lvalue_type ] * len (star_rv_types ))
1697
1701
else : # index lvalue
1698
1702
# TODO Figure out more precise type context, probably
@@ -1845,8 +1849,8 @@ def set_inferred_type(self, var: Var, lvalue: Lvalue, type: Type) -> None:
1845
1849
var .is_inferred = True
1846
1850
if isinstance (lvalue , MemberExpr ) and self .inferred_attribute_types is not None :
1847
1851
# Store inferred attribute type so that we can check consistency afterwards.
1848
- assert lvalue .def_var is not None
1849
- self .inferred_attribute_types [lvalue .def_var ] = type
1852
+ if lvalue .def_var is not None :
1853
+ self .inferred_attribute_types [lvalue .def_var ] = type
1850
1854
self .store_type (lvalue , type )
1851
1855
1852
1856
def set_inference_error_fallback_type (self , var : Var , lvalue : Lvalue , type : Type ,
@@ -2655,9 +2659,10 @@ def enter_partial_types(self) -> Iterator[None]:
2655
2659
if isinstance (var .type , PartialType ) and var .type .type is None :
2656
2660
# None partial type: assume variable is intended to have type None
2657
2661
var .type = NoneTyp ()
2658
- else :
2662
+ elif var not in self . partial_reported :
2659
2663
self .msg .fail (messages .NEED_ANNOTATION_FOR_VAR , context )
2660
2664
var .type = AnyType (TypeOfAny .from_error )
2665
+ self .partial_reported .add (var )
2661
2666
2662
2667
def find_partial_types (self , var : Var ) -> Optional [Dict [Var , Context ]]:
2663
2668
for partial_types in reversed (self .partial_types ):
0 commit comments