diff --git a/mypy/errors.py b/mypy/errors.py index 55f6f2b71655..6648784be310 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -27,10 +27,10 @@ class ErrorInfo: module = None # type: Optional[str] # The name of the type in which this error is located at. - type = '' # Unqualified, may be None + type = '' # type: Optional[str] # Unqualified, may be None # The name of the function or member in which this error is located at. - function_or_member = '' # Unqualified, may be None + function_or_member = '' # type: Optional[str] # Unqualified, may be None # The line number related to this error within file. line = 0 # -1 if unknown @@ -57,8 +57,8 @@ def __init__(self, import_ctx: List[Tuple[str, int]], file: str, module: Optional[str], - typ: str, - function_or_member: str, + typ: Optional[str], + function_or_member: Optional[str], line: int, column: int, severity: str, @@ -105,10 +105,10 @@ class Errors: file = None # type: str # Stack of short names of currents types (or None). - type_name = None # type: List[str] + type_name = None # type: List[Optional[str]] # Stack of short names of current functions or members (or None). - function_or_member = None # type: List[str] + function_or_member = None # type: List[Optional[str]] # Ignore errors on these lines of each file. ignored_lines = None # type: Dict[str, Set[int]] @@ -188,7 +188,7 @@ def set_file(self, file: str, module: Optional[str], ignored_lines: Set[int] = N self.target = [module] def set_file_ignored_lines(self, file: str, - ignored_lines: Set[int] = None, + ignored_lines: Set[int], ignore_all: bool = False) -> None: self.ignored_lines[file] = ignored_lines if ignore_all: @@ -265,7 +265,7 @@ def report(self, line: int, column: int, message: str, blocker: bool = False, only_once: if True, only report this exact message once per build origin_line: if non-None, override current context as origin """ - type = self.type_name[-1] + type = self.type_name[-1] # type: Optional[str] if len(self.function_or_member) > 2: type = None # Omit type context if nested function if file is None: @@ -362,7 +362,7 @@ def targets(self) -> Set[str]: for info in self.error_info if info.target) - def render_messages(self, errors: List[ErrorInfo]) -> List[Tuple[str, int, int, + def render_messages(self, errors: List[ErrorInfo]) -> List[Tuple[Optional[str], int, int, str, str]]: """Translate the messages into a sequence of tuples. @@ -371,12 +371,12 @@ def render_messages(self, errors: List[ErrorInfo]) -> List[Tuple[str, int, int, item may be None. If the line item is negative, the line number is not defined for the tuple. """ - result = [] # type: List[Tuple[str, int, int, str, str]] + result = [] # type: List[Tuple[Optional[str], int, int, str, str]] # (path, line, column, severity, message) prev_import_context = [] # type: List[Tuple[str, int]] - prev_function_or_member = None # type: str - prev_type = None # type: str + prev_function_or_member = None # type: Optional[str] + prev_type = None # type: Optional[str] for e in errors: # Report module import context, if different from previous message. @@ -460,10 +460,10 @@ def sort_messages(self, errors: List[ErrorInfo]) -> List[ErrorInfo]: result.extend(a) return result - def remove_duplicates(self, errors: List[Tuple[str, int, int, str, str]] - ) -> List[Tuple[str, int, int, str, str]]: + def remove_duplicates(self, errors: List[Tuple[Optional[str], int, int, str, str]] + ) -> List[Tuple[Optional[str], int, int, str, str]]: """Remove duplicates from a sorted error list.""" - res = [] # type: List[Tuple[str, int, int, str, str]] + res = [] # type: List[Tuple[Optional[str], int, int, str, str]] i = 0 while i < len(errors): dup = False diff --git a/mypy/maptype.py b/mypy/maptype.py index ff76035f2743..65c0143c38fb 100644 --- a/mypy/maptype.py +++ b/mypy/maptype.py @@ -28,7 +28,9 @@ def map_instance_to_supertypes(instance: Instance, # FIX: Currently we should only have one supertype per interface, so no # need to return an array result = [] # type: List[Instance] - for path in class_derivation_paths(instance.type, supertype): + typ = instance.type + assert typ is not None, 'Instance.type is not fixed after deserialization' + for path in class_derivation_paths(typ, supertype): types = [instance] for sup in path: a = [] # type: List[Instance] @@ -57,12 +59,14 @@ def class_derivation_paths(typ: TypeInfo, result = [] # type: List[List[TypeInfo]] for base in typ.bases: - if base.type == supertype: - result.append([base.type]) + btype = base.type + assert btype is not None, 'Instance.type is not fixed after deserialization' + if btype == supertype: + result.append([btype]) else: # Try constructing a longer path via the base class. - for path in class_derivation_paths(base.type, supertype): - result.append([base.type] + path) + for path in class_derivation_paths(btype, supertype): + result.append([btype] + path) return result @@ -71,6 +75,7 @@ def map_instance_to_direct_supertypes(instance: Instance, supertype: TypeInfo) -> List[Instance]: # FIX: There should only be one supertypes, always. typ = instance.type + assert typ is not None, 'Instance.type is not fixed after deserialization' result = [] # type: List[Instance] for b in typ.bases: @@ -98,4 +103,6 @@ def instance_to_type_environment(instance: Instance) -> Dict[TypeVarId, Type]: arguments. The type variables are mapped by their `id`. """ - return {binder.id: arg for binder, arg in zip(instance.type.defn.type_vars, instance.args)} + typ = instance.type + assert typ is not None, 'Instance.type is not fixed after deserialization' + return {binder.id: arg for binder, arg in zip(typ.defn.type_vars, instance.args)} diff --git a/mypy/nodes.py b/mypy/nodes.py index 0f4ae878cf60..2cd418e81f8d 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -872,9 +872,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class WhileStmt(Statement): expr = None # type: Expression body = None # type: Block - else_body = None # type: Block + else_body = None # type: Optional[Block] - def __init__(self, expr: Expression, body: Block, else_body: Block) -> None: + def __init__(self, expr: Expression, body: Block, else_body: Optional[Block]) -> None: self.expr = expr self.body = body self.else_body = else_body @@ -891,11 +891,11 @@ class ForStmt(Statement): # Expression to iterate expr = None # type: Expression body = None # type: Block - else_body = None # type: Block + else_body = None # type: Optional[Block] is_async = False # True if `async for ...` (PEP 492, Python 3.5) def __init__(self, index: Lvalue, expr: Expression, body: Block, - else_body: Block, index_type: 'mypy.types.Type' = None) -> None: + else_body: Optional[Block], index_type: 'mypy.types.Type' = None) -> None: self.index = index self.index_type = index_type self.expr = expr @@ -956,10 +956,10 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class IfStmt(Statement): expr = None # type: List[Expression] body = None # type: List[Block] - else_body = None # type: Block + else_body = None # type: Optional[Block] def __init__(self, expr: List[Expression], body: List[Block], - else_body: Block) -> None: + else_body: Optional[Block]) -> None: self.expr = expr self.body = body self.else_body = else_body @@ -969,10 +969,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class RaiseStmt(Statement): - expr = None # type: Expression - from_expr = None # type: Expression + # Plain 'raise' is a valid statement. + expr = None # type: Optional[Expression] + from_expr = None # type: Optional[Expression] - def __init__(self, expr: Expression, from_expr: Expression = None) -> None: + def __init__(self, expr: Optional[Expression], from_expr: Optional[Expression]) -> None: self.expr = expr self.from_expr = from_expr @@ -982,15 +983,17 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class TryStmt(Statement): body = None # type: Block # Try body - types = None # type: List[Expression] # Except type expressions - vars = None # type: List[NameExpr] # Except variable names + # Plain 'except:' also possible + types = None # type: List[Optional[Expression]] # Except type expressions + vars = None # type: List[Optional[NameExpr]] # Except variable names handlers = None # type: List[Block] # Except bodies - else_body = None # type: Block - finally_body = None # type: Block + else_body = None # type: Optional[Block] + finally_body = None # type: Optional[Block] - def __init__(self, body: Block, vars: List['NameExpr'], types: List[Expression], - handlers: List[Block], else_body: Block, - finally_body: Block) -> None: + def __init__(self, body: Block, vars: List[Optional['NameExpr']], + types: List[Optional[Expression]], + handlers: List[Block], else_body: Optional[Block], + finally_body: Optional[Block]) -> None: self.body = body self.vars = vars self.types = types @@ -1004,13 +1007,13 @@ def accept(self, visitor: StatementVisitor[T]) -> T: class WithStmt(Statement): expr = None # type: List[Expression] - target = None # type: List[Lvalue] + target = None # type: List[Optional[Lvalue]] # Type given by type comments for target, can be None target_type = None # type: mypy.types.Type body = None # type: Block is_async = False # True if `async with ...` (PEP 492, Python 3.5) - def __init__(self, expr: List[Expression], target: List[Lvalue], + def __init__(self, expr: List[Expression], target: List[Optional[Lvalue]], body: Block, target_type: 'mypy.types.Type' = None) -> None: self.expr = expr self.target = target @@ -1351,7 +1354,7 @@ class UnaryExpr(Expression): op = '' expr = None # type: Expression # Inferred operator method type - method_type = None # type: mypy.types.Type + method_type = None # type: Optional[mypy.types.Type] def __init__(self, op: str, expr: Expression) -> None: self.op = op @@ -1433,7 +1436,7 @@ class OpExpr(Expression): left = None # type: Expression right = None # type: Expression # Inferred type for the operator method type (when relevant). - method_type = None # type: mypy.types.Type + method_type = None # type: Optional[mypy.types.Type] def __init__(self, op: str, left: Expression, right: Expression) -> None: self.op = op @@ -1452,7 +1455,7 @@ class ComparisonExpr(Expression): operators = None # type: List[str] operands = None # type: List[Expression] # Inferred type for the operator methods (when relevant; None for 'is'). - method_types = None # type: List[mypy.types.Type] + method_types = None # type: List[Optional[mypy.types.Type]] def __init__(self, operators: List[str], operands: List[Expression]) -> None: self.operators = operators diff --git a/mypy/treetransform.py b/mypy/treetransform.py index f0a3bcba8caa..812eca8d4c71 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -3,7 +3,7 @@ Subclass TransformVisitor to perform non-trivial transformations. """ -from typing import List, Dict, cast +from typing import List, Dict, cast, Optional, Iterable from mypy.nodes import ( MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, @@ -76,7 +76,7 @@ def visit_import_all(self, node: ImportAll) -> ImportAll: return ImportAll(node.id, node.relative) def copy_argument(self, argument: Argument) -> Argument: - init_stmt = None # type: AssignmentStmt + init_stmt = None # type: Optional[AssignmentStmt] if argument.initialization_statement: init_lvalue = cast( @@ -360,7 +360,7 @@ def visit_yield_from_expr(self, node: YieldFromExpr) -> YieldFromExpr: return YieldFromExpr(self.expr(node.expr)) def visit_yield_expr(self, node: YieldExpr) -> YieldExpr: - return YieldExpr(self.expr(node.expr)) + return YieldExpr(self.optional_expr(node.expr)) def visit_await_expr(self, node: AwaitExpr) -> AwaitExpr: return AwaitExpr(self.expr(node.expr)) @@ -526,7 +526,7 @@ def stmt(self, stmt: Statement) -> Statement: # # All the node helpers also propagate line numbers. - def optional_expr(self, expr: Expression) -> Expression: + def optional_expr(self, expr: Optional[Expression]) -> Optional[Expression]: if expr: return self.expr(expr) else: @@ -537,7 +537,7 @@ def block(self, block: Block) -> Block: new.line = block.line return new - def optional_block(self, block: Block) -> Block: + def optional_block(self, block: Optional[Block]) -> Optional[Block]: if block: return self.block(block) else: @@ -549,7 +549,8 @@ def statements(self, statements: List[Statement]) -> List[Statement]: def expressions(self, expressions: List[Expression]) -> List[Expression]: return [self.expr(expr) for expr in expressions] - def optional_expressions(self, expressions: List[Expression]) -> List[Expression]: + def optional_expressions(self, expressions: Iterable[Optional[Expression]] + ) -> List[Optional[Expression]]: return [self.optional_expr(expr) for expr in expressions] def blocks(self, blocks: List[Block]) -> List[Block]: @@ -558,8 +559,8 @@ def blocks(self, blocks: List[Block]) -> List[Block]: def names(self, names: List[NameExpr]) -> List[NameExpr]: return [self.duplicate_name(name) for name in names] - def optional_names(self, names: List[NameExpr]) -> List[NameExpr]: - result = [] # type: List[NameExpr] + def optional_names(self, names: Iterable[Optional[NameExpr]]) -> List[Optional[NameExpr]]: + result = [] # type: List[Optional[NameExpr]] for name in names: if name: result.append(self.duplicate_name(name)) @@ -571,7 +572,7 @@ def type(self, type: Type) -> Type: # Override this method to transform types. return type - def optional_type(self, type: Type) -> Type: + def optional_type(self, type: Optional[Type]) -> Optional[Type]: if type: return self.type(type) else: diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 877714581080..21721325ebbc 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -43,7 +43,7 @@ def analyze_type_alias(node: Expression, lookup_fqn_func: Callable[[str], SymbolTableNode], tvar_scope: TypeVarScope, fail_func: Callable[[str, Context], None], - allow_unnormalized: bool = False) -> Type: + allow_unnormalized: bool = False) -> Optional[Type]: """Return type if node is valid as a type alias rvalue. Return None otherwise. 'node' must have been semantically analyzed. @@ -139,8 +139,8 @@ def visit_unbound_type(self, t: UnboundType) -> Type: if (fullname in nongen_builtins and t.args and not sym.normalized and not self.allow_unnormalized): self.fail(no_subscript_builtin_alias(fullname), t) - if sym.kind == TVAR and self.tvar_scope.get_binding(sym) is not None: - tvar_def = self.tvar_scope.get_binding(sym) + tvar_def = self.tvar_scope.get_binding(sym) + if sym.kind == TVAR and tvar_def is not None: if len(t.args) > 0: self.fail('Type variable "{}" used with arguments'.format( t.name), t) @@ -196,6 +196,7 @@ def visit_unbound_type(self, t: UnboundType) -> Type: return UninhabitedType(is_noreturn=True) elif sym.kind == TYPE_ALIAS: override = sym.type_override + assert override is not None an_args = self.anal_array(t.args) all_vars = self.get_type_var_names(override) exp_len = len(all_vars) @@ -453,7 +454,9 @@ def bind_function_type_variables(self, if not self.tvar_scope.allow_binding(tvar.fullname()): self.fail("Type variable '{}' is bound by an outer class".format(name), defn) self.tvar_scope.bind(name, tvar) - defs.append(self.tvar_scope.get_binding(tvar.fullname())) + binding = self.tvar_scope.get_binding(tvar.fullname()) + assert binding is not None + defs.append(binding) return defs