diff --git a/mypy/checker.py b/mypy/checker.py index 488f3185e897..99dd8e801c0c 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -180,6 +180,8 @@ def check_first_pass(self) -> None: all_ = self.globals.get('__all__') if all_ is not None and all_.type is not None: + all_node = all_.node + assert all_node is not None seq_str = self.named_generic_type('typing.Sequence', [self.named_type('builtins.str')]) if self.options.python_version[0] < 3: @@ -188,7 +190,7 @@ def check_first_pass(self) -> None: if not is_subtype(all_.type, seq_str): str_seq_s, all_s = self.msg.format_distinctly(seq_str, all_.type) self.fail(messages.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s), - all_.node) + all_node) def check_second_pass(self, todo: List[DeferredNode] = None) -> bool: """Run second or following pass of type checking. @@ -346,12 +348,13 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None: self.msg.overloaded_signatures_arg_specific(i + 1, defn.impl) impl_type_subst = impl_type if impl_type.variables: - impl_type_subst = unify_generic_callable(impl_type, sig1, ignore_return=False) - if impl_type_subst is None: + unified = unify_generic_callable(impl_type, sig1, ignore_return=False) + if unified is None: self.fail("Type variable mismatch between " + "overload signature {} and implementation".format(i + 1), defn.impl) return + impl_type_subst = unified if not is_subtype(sig1.ret_type, impl_type_subst.ret_type): self.msg.overloaded_signatures_ret_specific(i + 1, defn.impl) @@ -593,7 +596,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: not isinstance(typ.ret_type, NoneTyp) and not self.dynamic_funcs[-1]): self.fail(messages.MUST_HAVE_NONE_RETURN_TYPE.format(fdef.name()), - item.type) + item) show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub if self.options.disallow_untyped_defs and show_untyped: @@ -1257,7 +1260,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type self.infer_variable_type(inferred, lvalue, self.expr_checker.accept(rvalue), rvalue) - def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type, + def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Optional[Type], rvalue: Expression) -> bool: lvalue_node = lvalue.node @@ -1300,8 +1303,9 @@ def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type, break return False - def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Type, rvalue: Expression, - base: TypeInfo, base_type: Type, base_node: Node) -> bool: + def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type], + rvalue: Expression, base: TypeInfo, base_type: Type, + base_node: Node) -> bool: lvalue_node = lvalue.node assert isinstance(lvalue_node, Var) @@ -1574,10 +1578,12 @@ def check_multi_assignment_from_iterable(self, lvalues: List[Lvalue], rvalue_typ else: self.msg.type_not_iterable(rvalue_type, context) - def check_lvalue(self, lvalue: Lvalue) -> Tuple[Type, IndexExpr, Var]: - lvalue_type = None # type: Type - index_lvalue = None # type: IndexExpr - inferred = None # type: Var + def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type], + Optional[IndexExpr], + Optional[Var]]: + lvalue_type = None # type: Optional[Type] + index_lvalue = None # type: Optional[IndexExpr] + inferred = None # type: Optional[Var] if self.is_definition(lvalue): if isinstance(lvalue, NameExpr): @@ -2750,8 +2756,8 @@ def find_isinstance_check(node: Expression, # Check for `x is None` and `x is not None`. is_not = node.operators == ['is not'] if any(is_literal_none(n) for n in node.operands) and (is_not or node.operators == ['is']): - if_vars = {} # type: Dict[Expression, Type] - else_vars = {} # type: Dict[Expression, Type] + if_vars = {} # type: TypeMap + else_vars = {} # type: TypeMap for expr in node.operands: if expr.literal == LITERAL_TYPE and not is_literal_none(expr) and expr in type_map: # This should only be true at most once: there should be @@ -2829,7 +2835,8 @@ def flatten_types(t: Type) -> List[Type]: return [t] -def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> List[TypeRange]: +def get_isinstance_type(expr: Expression, + type_map: Dict[Expression, Type]) -> Optional[List[TypeRange]]: all_types = flatten_types(type_map[expr]) types = [] # type: List[TypeRange] for typ in all_types: diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 9e44142302fa..b19a0a1bcfd2 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -123,7 +123,7 @@ def visit_name_expr(self, e: NameExpr) -> Type: return self.narrow_type_from_binder(e, result) def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: - result = None # type: Type + result = None # type: Optional[Type] node = e.node if isinstance(node, Var): # Variable reference. @@ -157,6 +157,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: # Unknown reference; use any type implicitly to avoid # generating extra type errors. result = AnyType() + assert result is not None return result 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: # i.e. its constructor (a poor approximation for reality, # but better than AnyType...), but replace the return type # with typevar. - callee = self.analyze_type_type_callee(item.upper_bound, context) + callee = self.analyze_type_type_callee(item.upper_bound, + context) # type: Optional[Type] if isinstance(callee, CallableType): if callee.is_generic(): callee = None diff --git a/mypy/checkmember.py b/mypy/checkmember.py index d4ca8b0f2e8d..ed3239a2bb46 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -381,7 +381,7 @@ def analyze_class_attribute_access(itype: Instance, builtin_type: Callable[[str], Instance], not_ready_callback: Callable[[str, Context], None], msg: MessageBuilder, - original_type: Type) -> Type: + original_type: Type) -> Optional[Type]: """original_type is the type of E in the expression E.var""" node = itype.type.get(name) if not node: @@ -403,7 +403,9 @@ def analyze_class_attribute_access(itype: Instance, t = node.type if t: if isinstance(t, PartialType): - return handle_partial_attribute_type(t, is_lvalue, msg, node.node) + symnode = node.node + assert symnode is not None + return handle_partial_attribute_type(t, is_lvalue, msg, symnode) if not is_method and (isinstance(t, TypeVarType) or get_type_vars(t)): msg.fail(messages.GENERIC_INSTANCE_VAR_CLASS_ACCESS, context) 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, # We need to first map B's __init__ to the type (List[T]) -> None. signature = cast(FunctionLike, map_type_from_supertype(signature, info, init_or_new.info)) - + special_sig = None # type: Optional[str] if init_or_new.info.fullname() == 'builtins.dict': # Special signature! special_sig = 'dict' - else: - special_sig = None if isinstance(signature, CallableType): return class_callable(signature, info, fallback, special_sig) @@ -630,6 +630,7 @@ class B(A): pass self_param_type, original_type)[0] def expand(target: Type) -> Type: + assert typearg is not None return expand_type(target, {func.variables[0].id: typearg}) arg_types = [expand(x) for x in func.arg_types[1:]] diff --git a/mypy/constraints.py b/mypy/constraints.py index 006e255fa9ea..d65a418df37b 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -25,7 +25,7 @@ class Constraint: It can be either T <: type or T :> type (T is a type variable). """ - type_var = None # Type variable id + type_var = None # type: TypeVarId op = 0 # SUBTYPE_OF or SUPERTYPE_OF target = None # type: Type @@ -53,10 +53,11 @@ def infer_constraints_for_callable( for i, actuals in enumerate(formal_to_actual): for actual in actuals: - if arg_types[actual] is None: + actual_arg_type = arg_types[actual] + if actual_arg_type is None: continue - actual_type = get_actual_type(arg_types[actual], arg_kinds[actual], + actual_type = get_actual_type(actual_arg_type, arg_kinds[actual], tuple_counter) c = infer_constraints(callee.arg_types[i], actual_type, SUPERTYPE_OF) diff --git a/mypy/exprtotype.py b/mypy/exprtotype.py index 1d095f445b02..b99f1a653d05 100644 --- a/mypy/exprtotype.py +++ b/mypy/exprtotype.py @@ -50,6 +50,7 @@ def expr_to_unanalyzed_type(expr: Expression) -> Type: # Parse string literal type. try: result = parse_type_comment(expr.value, expr.line, None) + assert result is not None except SyntaxError: raise TypeTranslationError() return result diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 19619cf58c6b..35efcb38eb49 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -95,7 +95,7 @@ def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None, return tree -def parse_type_comment(type_comment: str, line: int, errors: Errors) -> Optional[Type]: +def parse_type_comment(type_comment: str, line: int, errors: Optional[Errors]) -> Optional[Type]: try: typ = ast3.parse(type_comment, '', 'eval') except SyntaxError as e: diff --git a/mypy/infer.py b/mypy/infer.py index 0047fe4536d3..6820a2c05eb4 100644 --- a/mypy/infer.py +++ b/mypy/infer.py @@ -12,7 +12,7 @@ def infer_function_type_arguments(callee_type: CallableType, arg_types: List[Optional[Type]], arg_kinds: List[int], formal_to_actual: List[List[int]], - strict: bool = True) -> List[Type]: + strict: bool = True) -> List[Optional[Type]]: """Infer the type arguments of a generic function. 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, def infer_type_arguments(type_var_ids: List[TypeVarId], - template: Type, actual: Type) -> List[Type]: + template: Type, actual: Type) -> List[Optional[Type]]: # Like infer_function_type_arguments, but only match a single type # against a generic type. constraints = infer_constraints(template, actual, SUBTYPE_OF) diff --git a/mypy/join.py b/mypy/join.py index b4866bdbc691..586d281adbb8 100644 --- a/mypy/join.py +++ b/mypy/join.py @@ -1,7 +1,7 @@ """Calculation of the least upper bound types (joins).""" from collections import OrderedDict -from typing import cast, List +from typing import cast, List, Optional from mypy.types import ( Type, AnyType, NoneTyp, TypeVisitor, Instance, UnboundType, @@ -305,7 +305,7 @@ def join_instances_via_supertype(t: Instance, s: Instance) -> Type: # Compute the "best" supertype of t when joined with s. # The definition of "best" may evolve; for now it is the one with # the longest MRO. Ties are broken by using the earlier base. - best = None # type: Type + best = None # type: Optional[Type] for base in t.type.bases: mapped = map_instance_to_supertype(t, base.type) res = join_instances(mapped, s) diff --git a/mypy/meet.py b/mypy/meet.py index feda9bea1854..e32997fc43c5 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -1,5 +1,5 @@ from collections import OrderedDict -from typing import List, Optional +from typing import List, Optional, cast, Tuple from mypy.join import is_similar_callables, combine_similar_callables, join_type_list from mypy.types import ( @@ -255,10 +255,15 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type: for (_, l, r) in self.s.zip(t): if not is_equivalent(l, r): return self.default(self.s) - items = OrderedDict([ - (item_name, s_item_type or t_item_type) - for (item_name, s_item_type, t_item_type) in self.s.zipall(t) - ]) + item_list = [] # type: List[Tuple[str, Type]] + for (item_name, s_item_type, t_item_type) in self.s.zipall(t): + if s_item_type is not None: + item_list.append((item_name, s_item_type)) + else: + # at least one of s_item_type and t_item_type is not None + assert t_item_type is not None + item_list.append((item_name, t_item_type)) + items = OrderedDict(item_list) mapping_value_type = join_type_list(list(items.values())) fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type) return TypedDictType(items, fallback) diff --git a/mypy/nodes.py b/mypy/nodes.py index 222a912286ca..c5c354cfea55 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -366,9 +366,9 @@ class FuncBase(Node): # Type signature. This is usually CallableType or Overloaded, but it can be something else for # decorated functions/ - type = None # type: mypy.types.Type + type = None # type: Optional[mypy.types.Type] # Original, not semantically analyzed type (used for reprocessing) - unanalyzed_type = None # type: mypy.types.Type + unanalyzed_type = None # type: Optional[mypy.types.Type] # If method, reference to TypeInfo info = None # type: TypeInfo is_property = False @@ -596,9 +596,10 @@ def deserialize(cls, data: JsonDict) -> 'FuncDef': ret.arg_names = data['arg_names'] ret.arg_kinds = data['arg_kinds'] # Mark these as 'None' so that future uses will trigger an error - ret.arguments = None - ret.max_pos = None - ret.min_args = None + _dummy = None # type: Any + ret.arguments = _dummy + ret.max_pos = _dummy + ret.min_args = _dummy return ret @@ -655,7 +656,7 @@ class Var(SymbolNode): _name = None # type: str # Name without module prefix _fullname = None # type: str # Name with module prefix info = None # type: TypeInfo # Defining class (for member variables) - type = None # type: mypy.types.Type # Declared or inferred type, or None + type = None # type: Optional[mypy.types.Type] # Declared or inferred type, or None # Is this the first argument to an ordinary method (usually "self")? is_self = False is_ready = False # If inferred, is the inferred type available? @@ -727,7 +728,7 @@ class ClassDef(Statement): # Base class expressions (not semantically analyzed -- can be arbitrary expressions) base_type_exprs = None # type: List[Expression] info = None # type: TypeInfo # Related TypeInfo - metaclass = '' + metaclass = '' # type: Optional[str] decorators = None # type: List[Expression] has_incompatible_baseclass = False @@ -835,7 +836,7 @@ class AssignmentStmt(Statement): lvalues = None # type: List[Lvalue] rvalue = None # type: Expression # Declared type in a comment, may be None. - type = None # type: mypy.types.Type + type = None # type: Optional[mypy.types.Type] # Original, not semantically analyzed type in annotation (used for reprocessing) unanalyzed_type = None # type: Optional[mypy.types.Type] # This indicates usage of PEP 526 type annotation syntax in assignment. @@ -887,7 +888,7 @@ class ForStmt(Statement): # Index variables index = None # type: Lvalue # Type given by type comments for index, can be None - index_type = None # type: mypy.types.Type + index_type = None # type: Optional[mypy.types.Type] # Expression to iterate expr = None # type: Expression body = None # type: Block @@ -1009,7 +1010,7 @@ class WithStmt(Statement): expr = None # type: List[Expression] target = None # type: List[Optional[Lvalue]] # Type given by type comments for target, can be None - target_type = None # type: mypy.types.Type + target_type = None # type: Optional[mypy.types.Type] body = None # type: Block is_async = False # True if `async with ...` (PEP 492, Python 3.5) @@ -1185,7 +1186,7 @@ class RefExpr(Expression): """Abstract base class for name-like constructs""" kind = None # type: int # LDEF/GDEF/MDEF/... (None if not available) - node = None # type: SymbolNode # Var, FuncDef or TypeInfo that describes this + node = None # type: Optional[SymbolNode] # Var, FuncDef or TypeInfo that describes this fullname = None # type: str # Fully qualified name (or name if not global) # Does this define a new name with inferred type? @@ -1281,13 +1282,13 @@ class CallExpr(Expression): args = None # type: List[Expression] arg_kinds = None # type: List[int] # ARG_ constants # Each name can be None if not a keyword argument. - arg_names = None # type: List[str] + arg_names = None # type: List[Optional[str]] # If not None, the node that represents the meaning of the CallExpr. For # cast(...) this is a CastExpr. analyzed = None # type: Optional[Expression] def __init__(self, callee: Expression, args: List[Expression], arg_kinds: List[int], - arg_names: List[str] = None, analyzed: Expression = None) -> None: + arg_names: List[Optional[str]] = None, analyzed: Expression = None) -> None: if not arg_names: arg_names = [None] * len(args) @@ -1333,7 +1334,7 @@ class IndexExpr(Expression): method_type = None # type: mypy.types.Type # If not None, this is actually semantically a type application # Class[type, ...] or a type alias initializer. - analyzed = None # type: Union[TypeApplication, TypeAliasExpr] + analyzed = None # type: Union[TypeApplication, TypeAliasExpr, None] def __init__(self, base: Expression, index: Expression) -> None: self.base = base @@ -1538,7 +1539,9 @@ def name(self) -> str: def expr(self) -> Expression: """Return the expression (the body) of the lambda.""" ret = cast(ReturnStmt, self.body.body[-1]) - return ret.expr + expr = ret.expr + assert expr is not None # lambda can't have empty body + return expr def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_lambda_expr(self) @@ -1795,7 +1798,7 @@ class TypeAliasExpr(Expression): type = None # type: mypy.types.Type # Simple fallback type for aliases that are invalid in runtime expressions # (for example Union, Tuple, Callable). - fallback = None # type: mypy.types.Type + fallback = None # type: Optional[mypy.types.Type] # This type alias is subscripted in a runtime expression like Alias[int](42) # (not in a type context like type annotation or base class). in_runtime = False # type: bool @@ -1970,7 +1973,7 @@ class is generic then it will be a type constructor of higher kind. # even though it's not a subclass in Python. The non-standard # `@_promote` decorator introduces this, and there are also # several builtin examples, in particular `int` -> `float`. - _promote = None # type: mypy.types.Type + _promote = None # type: Optional[mypy.types.Type] # Representation of a Tuple[...] base class, if the class has any # (e.g., for named tuples). If this is not None, the actual Type @@ -2025,7 +2028,7 @@ def is_generic(self) -> bool: """Is the type generic (i.e. does it have type variables)?""" return len(self.type_vars) > 0 - def get(self, name: str) -> 'SymbolTableNode': + def get(self, name: str) -> Optional['SymbolTableNode']: for cls in self.mro: n = cls.names.get(name) if n: @@ -2051,7 +2054,7 @@ def has_readable_member(self, name: str) -> bool: def has_method(self, name: str) -> bool: return self.get_method(name) is not None - def get_method(self, name: str) -> FuncBase: + def get_method(self, name: str) -> Optional[FuncBase]: if self.mro is None: # Might be because of a previous error. return None for cls in self.mro: @@ -2136,7 +2139,7 @@ def dump(self, """Return a string dump of the contents of the TypeInfo.""" if not str_conv: str_conv = mypy.strconv.StrConv() - base = None # type: str + base = '' # type: str def type_str(typ: 'mypy.types.Type') -> str: if type_str_conv: @@ -2239,7 +2242,7 @@ class SymbolTableNode: # or None for a bound type variable). node = None # type: Optional[SymbolNode] # Module id (e.g. "foo.bar") or None - mod_id = '' + mod_id = '' # type: Optional[str] # If this not None, override the type of the 'node' attribute. type_override = None # type: Optional[mypy.types.Type] # If False, this name won't be imported via 'from import *'. @@ -2262,14 +2265,14 @@ def __init__(self, kind: int, node: Optional[SymbolNode], mod_id: str = None, self.normalized = normalized @property - def fullname(self) -> str: + def fullname(self) -> Optional[str]: if self.node is not None: return self.node.fullname() else: return None @property - def type(self) -> 'mypy.types.Type': + def type(self) -> Optional['mypy.types.Type']: # IDEA: Get rid of the Any type. node = self.node # type: Any if self.type_override is not None: @@ -2424,12 +2427,13 @@ def set_flags(node: Node, flags: List[str]) -> None: setattr(node, name, True) -def get_member_expr_fullname(expr: MemberExpr) -> str: +def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]: """Return the qualified name representation of a member expression. Return a string of form foo.bar, foo.bar.baz, or similar, or None if the argument cannot be represented in this form. """ + initial = None # type: Optional[str] if isinstance(expr.expr, NameExpr): initial = expr.expr.name elif isinstance(expr.expr, MemberExpr): diff --git a/mypy/solve.py b/mypy/solve.py index 5d2cca0edef8..ad6a8829da04 100644 --- a/mypy/solve.py +++ b/mypy/solve.py @@ -1,6 +1,6 @@ """Type inference constraint solving""" -from typing import List, Dict +from typing import List, Dict, Optional from collections import defaultdict from mypy.types import Type, NoneTyp, AnyType, UninhabitedType, TypeVarId @@ -13,7 +13,7 @@ def solve_constraints(vars: List[TypeVarId], constraints: List[Constraint], - strict: bool =True) -> List[Type]: + strict: bool =True) -> List[Optional[Type]]: """Solve type constraints. Return the best type(s) for type variables; each type can be None if the value of the variable @@ -28,12 +28,13 @@ def solve_constraints(vars: List[TypeVarId], constraints: List[Constraint], for con in constraints: cmap[con.type_var].append(con) - res = [] # type: List[Type] + res = [] # type: List[Optional[Type]] # Solve each type variable separately. for tvar in vars: - bottom = None # type: Type - top = None # type: Type + bottom = None # type: Optional[Type] + top = None # type: Optional[Type] + candidate = None # type: Optional[Type] # Process each constraint separately, and calculate the lower and upper # bounds based on constraints. Note that we assume that the constraint diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 3388c291920d..6535dfd4496a 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict, Callable +from typing import List, Optional, Dict, Callable, cast from mypy.types import ( Type, AnyType, UnboundType, TypeVisitor, FormalArgument, NoneTyp, @@ -514,8 +514,10 @@ def unify_generic_callable(type: CallableType, target: CallableType, inferred_vars = mypy.solve.solve_constraints(type_var_ids, constraints) if None in inferred_vars: return None + non_none_inferred_vars = cast(List[Type], inferred_vars) msg = messages.temp_message_builder() - applied = mypy.applytype.apply_generic_arguments(type, inferred_vars, msg, context=target) + applied = mypy.applytype.apply_generic_arguments(type, non_none_inferred_vars, msg, + context=target) if msg.is_errors(): return None return applied diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 812eca8d4c71..170be48da9c5 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -166,7 +166,7 @@ def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> OverloadedFuncDe newitem.line = olditem.line new = OverloadedFuncDef(items) new._fullname = node._fullname - new.type = self.type(node.type) + new.type = self.optional_type(node.type) new.info = node.info if node.impl: new.impl = cast(OverloadPart, node.impl.accept(self))