Skip to content

Commit 058a8a6

Browse files
ilevkivskyigvanrossum
authored andcommitted
[clean strict optional] Fix more strict optional errors (#3292)
1 parent 88fe21d commit 058a8a6

13 files changed

+90
-66
lines changed

mypy/checker.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ def check_first_pass(self) -> None:
180180

181181
all_ = self.globals.get('__all__')
182182
if all_ is not None and all_.type is not None:
183+
all_node = all_.node
184+
assert all_node is not None
183185
seq_str = self.named_generic_type('typing.Sequence',
184186
[self.named_type('builtins.str')])
185187
if self.options.python_version[0] < 3:
@@ -188,7 +190,7 @@ def check_first_pass(self) -> None:
188190
if not is_subtype(all_.type, seq_str):
189191
str_seq_s, all_s = self.msg.format_distinctly(seq_str, all_.type)
190192
self.fail(messages.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s),
191-
all_.node)
193+
all_node)
192194

193195
def check_second_pass(self, todo: List[DeferredNode] = None) -> bool:
194196
"""Run second or following pass of type checking.
@@ -346,12 +348,13 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
346348
self.msg.overloaded_signatures_arg_specific(i + 1, defn.impl)
347349
impl_type_subst = impl_type
348350
if impl_type.variables:
349-
impl_type_subst = unify_generic_callable(impl_type, sig1, ignore_return=False)
350-
if impl_type_subst is None:
351+
unified = unify_generic_callable(impl_type, sig1, ignore_return=False)
352+
if unified is None:
351353
self.fail("Type variable mismatch between " +
352354
"overload signature {} and implementation".format(i + 1),
353355
defn.impl)
354356
return
357+
impl_type_subst = unified
355358
if not is_subtype(sig1.ret_type, impl_type_subst.ret_type):
356359
self.msg.overloaded_signatures_ret_specific(i + 1, defn.impl)
357360

@@ -593,7 +596,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None:
593596
not isinstance(typ.ret_type, NoneTyp) and
594597
not self.dynamic_funcs[-1]):
595598
self.fail(messages.MUST_HAVE_NONE_RETURN_TYPE.format(fdef.name()),
596-
item.type)
599+
item)
597600

598601
show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub
599602
if self.options.disallow_untyped_defs and show_untyped:
@@ -1257,7 +1260,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
12571260
self.infer_variable_type(inferred, lvalue, self.expr_checker.accept(rvalue),
12581261
rvalue)
12591262

1260-
def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type,
1263+
def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Optional[Type],
12611264
rvalue: Expression) -> bool:
12621265
lvalue_node = lvalue.node
12631266

@@ -1300,8 +1303,9 @@ def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type,
13001303
break
13011304
return False
13021305

1303-
def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Type, rvalue: Expression,
1304-
base: TypeInfo, base_type: Type, base_node: Node) -> bool:
1306+
def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type],
1307+
rvalue: Expression, base: TypeInfo, base_type: Type,
1308+
base_node: Node) -> bool:
13051309
lvalue_node = lvalue.node
13061310
assert isinstance(lvalue_node, Var)
13071311

@@ -1574,10 +1578,12 @@ def check_multi_assignment_from_iterable(self, lvalues: List[Lvalue], rvalue_typ
15741578
else:
15751579
self.msg.type_not_iterable(rvalue_type, context)
15761580

1577-
def check_lvalue(self, lvalue: Lvalue) -> Tuple[Type, IndexExpr, Var]:
1578-
lvalue_type = None # type: Type
1579-
index_lvalue = None # type: IndexExpr
1580-
inferred = None # type: Var
1581+
def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type],
1582+
Optional[IndexExpr],
1583+
Optional[Var]]:
1584+
lvalue_type = None # type: Optional[Type]
1585+
index_lvalue = None # type: Optional[IndexExpr]
1586+
inferred = None # type: Optional[Var]
15811587

15821588
if self.is_definition(lvalue):
15831589
if isinstance(lvalue, NameExpr):
@@ -2750,8 +2756,8 @@ def find_isinstance_check(node: Expression,
27502756
# Check for `x is None` and `x is not None`.
27512757
is_not = node.operators == ['is not']
27522758
if any(is_literal_none(n) for n in node.operands) and (is_not or node.operators == ['is']):
2753-
if_vars = {} # type: Dict[Expression, Type]
2754-
else_vars = {} # type: Dict[Expression, Type]
2759+
if_vars = {} # type: TypeMap
2760+
else_vars = {} # type: TypeMap
27552761
for expr in node.operands:
27562762
if expr.literal == LITERAL_TYPE and not is_literal_none(expr) and expr in type_map:
27572763
# This should only be true at most once: there should be
@@ -2829,7 +2835,8 @@ def flatten_types(t: Type) -> List[Type]:
28292835
return [t]
28302836

28312837

2832-
def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> List[TypeRange]:
2838+
def get_isinstance_type(expr: Expression,
2839+
type_map: Dict[Expression, Type]) -> Optional[List[TypeRange]]:
28332840
all_types = flatten_types(type_map[expr])
28342841
types = [] # type: List[TypeRange]
28352842
for typ in all_types:

mypy/checkexpr.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def visit_name_expr(self, e: NameExpr) -> Type:
123123
return self.narrow_type_from_binder(e, result)
124124

125125
def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
126-
result = None # type: Type
126+
result = None # type: Optional[Type]
127127
node = e.node
128128
if isinstance(node, Var):
129129
# Variable reference.
@@ -157,6 +157,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
157157
# Unknown reference; use any type implicitly to avoid
158158
# generating extra type errors.
159159
result = AnyType()
160+
assert result is not None
160161
return result
161162

162163
def analyze_var_ref(self, var: Var, context: Context) -> Type:
@@ -468,7 +469,8 @@ def analyze_type_type_callee(self, item: Type, context: Context) -> Type:
468469
# i.e. its constructor (a poor approximation for reality,
469470
# but better than AnyType...), but replace the return type
470471
# with typevar.
471-
callee = self.analyze_type_type_callee(item.upper_bound, context)
472+
callee = self.analyze_type_type_callee(item.upper_bound,
473+
context) # type: Optional[Type]
472474
if isinstance(callee, CallableType):
473475
if callee.is_generic():
474476
callee = None

mypy/checkmember.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ def analyze_class_attribute_access(itype: Instance,
381381
builtin_type: Callable[[str], Instance],
382382
not_ready_callback: Callable[[str, Context], None],
383383
msg: MessageBuilder,
384-
original_type: Type) -> Type:
384+
original_type: Type) -> Optional[Type]:
385385
"""original_type is the type of E in the expression E.var"""
386386
node = itype.type.get(name)
387387
if not node:
@@ -403,7 +403,9 @@ def analyze_class_attribute_access(itype: Instance,
403403
t = node.type
404404
if t:
405405
if isinstance(t, PartialType):
406-
return handle_partial_attribute_type(t, is_lvalue, msg, node.node)
406+
symnode = node.node
407+
assert symnode is not None
408+
return handle_partial_attribute_type(t, is_lvalue, msg, symnode)
407409
if not is_method and (isinstance(t, TypeVarType) or get_type_vars(t)):
408410
msg.fail(messages.GENERIC_INSTANCE_VAR_CLASS_ACCESS, context)
409411
is_classmethod = is_decorated and cast(Decorator, node.node).func.is_class
@@ -515,12 +517,10 @@ def type_object_type_from_function(init_or_new: FuncBase, info: TypeInfo,
515517
# We need to first map B's __init__ to the type (List[T]) -> None.
516518
signature = cast(FunctionLike,
517519
map_type_from_supertype(signature, info, init_or_new.info))
518-
520+
special_sig = None # type: Optional[str]
519521
if init_or_new.info.fullname() == 'builtins.dict':
520522
# Special signature!
521523
special_sig = 'dict'
522-
else:
523-
special_sig = None
524524

525525
if isinstance(signature, CallableType):
526526
return class_callable(signature, info, fallback, special_sig)
@@ -630,6 +630,7 @@ class B(A): pass
630630
self_param_type, original_type)[0]
631631

632632
def expand(target: Type) -> Type:
633+
assert typearg is not None
633634
return expand_type(target, {func.variables[0].id: typearg})
634635

635636
arg_types = [expand(x) for x in func.arg_types[1:]]

mypy/constraints.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Constraint:
2525
It can be either T <: type or T :> type (T is a type variable).
2626
"""
2727

28-
type_var = None # Type variable id
28+
type_var = None # type: TypeVarId
2929
op = 0 # SUBTYPE_OF or SUPERTYPE_OF
3030
target = None # type: Type
3131

@@ -53,10 +53,11 @@ def infer_constraints_for_callable(
5353

5454
for i, actuals in enumerate(formal_to_actual):
5555
for actual in actuals:
56-
if arg_types[actual] is None:
56+
actual_arg_type = arg_types[actual]
57+
if actual_arg_type is None:
5758
continue
5859

59-
actual_type = get_actual_type(arg_types[actual], arg_kinds[actual],
60+
actual_type = get_actual_type(actual_arg_type, arg_kinds[actual],
6061
tuple_counter)
6162
c = infer_constraints(callee.arg_types[i], actual_type,
6263
SUPERTYPE_OF)

mypy/exprtotype.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def expr_to_unanalyzed_type(expr: Expression) -> Type:
5050
# Parse string literal type.
5151
try:
5252
result = parse_type_comment(expr.value, expr.line, None)
53+
assert result is not None
5354
except SyntaxError:
5455
raise TypeTranslationError()
5556
return result

mypy/fastparse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
9595
return tree
9696

9797

98-
def parse_type_comment(type_comment: str, line: int, errors: Errors) -> Optional[Type]:
98+
def parse_type_comment(type_comment: str, line: int, errors: Optional[Errors]) -> Optional[Type]:
9999
try:
100100
typ = ast3.parse(type_comment, '<type_comment>', 'eval')
101101
except SyntaxError as e:

mypy/infer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def infer_function_type_arguments(callee_type: CallableType,
1212
arg_types: List[Optional[Type]],
1313
arg_kinds: List[int],
1414
formal_to_actual: List[List[int]],
15-
strict: bool = True) -> List[Type]:
15+
strict: bool = True) -> List[Optional[Type]]:
1616
"""Infer the type arguments of a generic function.
1717
1818
Return an array of lower bound types for the type variables -1 (at
@@ -36,7 +36,7 @@ def infer_function_type_arguments(callee_type: CallableType,
3636

3737

3838
def infer_type_arguments(type_var_ids: List[TypeVarId],
39-
template: Type, actual: Type) -> List[Type]:
39+
template: Type, actual: Type) -> List[Optional[Type]]:
4040
# Like infer_function_type_arguments, but only match a single type
4141
# against a generic type.
4242
constraints = infer_constraints(template, actual, SUBTYPE_OF)

mypy/join.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Calculation of the least upper bound types (joins)."""
22

33
from collections import OrderedDict
4-
from typing import cast, List
4+
from typing import cast, List, Optional
55

66
from mypy.types import (
77
Type, AnyType, NoneTyp, TypeVisitor, Instance, UnboundType,
@@ -305,7 +305,7 @@ def join_instances_via_supertype(t: Instance, s: Instance) -> Type:
305305
# Compute the "best" supertype of t when joined with s.
306306
# The definition of "best" may evolve; for now it is the one with
307307
# the longest MRO. Ties are broken by using the earlier base.
308-
best = None # type: Type
308+
best = None # type: Optional[Type]
309309
for base in t.type.bases:
310310
mapped = map_instance_to_supertype(t, base.type)
311311
res = join_instances(mapped, s)

mypy/meet.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from collections import OrderedDict
2-
from typing import List, Optional
2+
from typing import List, Optional, cast, Tuple
33

44
from mypy.join import is_similar_callables, combine_similar_callables, join_type_list
55
from mypy.types import (
@@ -255,10 +255,15 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type:
255255
for (_, l, r) in self.s.zip(t):
256256
if not is_equivalent(l, r):
257257
return self.default(self.s)
258-
items = OrderedDict([
259-
(item_name, s_item_type or t_item_type)
260-
for (item_name, s_item_type, t_item_type) in self.s.zipall(t)
261-
])
258+
item_list = [] # type: List[Tuple[str, Type]]
259+
for (item_name, s_item_type, t_item_type) in self.s.zipall(t):
260+
if s_item_type is not None:
261+
item_list.append((item_name, s_item_type))
262+
else:
263+
# at least one of s_item_type and t_item_type is not None
264+
assert t_item_type is not None
265+
item_list.append((item_name, t_item_type))
266+
items = OrderedDict(item_list)
262267
mapping_value_type = join_type_list(list(items.values()))
263268
fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type)
264269
return TypedDictType(items, fallback)

0 commit comments

Comments
 (0)