-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Tighter types for strconv, report and check* #2223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
|
||
from mypy.errors import Errors, report_internal_error | ||
from mypy.nodes import ( | ||
SymbolTable, Node, MypyFile, Var, Expression, Lvalue, | ||
SymbolTable, Statement, MypyFile, Var, Expression, Lvalue, | ||
OverloadedFuncDef, FuncDef, FuncItem, FuncBase, TypeInfo, | ||
ClassDef, GDEF, Block, AssignmentStmt, NameExpr, MemberExpr, IndexExpr, | ||
TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, IfStmt, | ||
|
@@ -64,7 +64,7 @@ | |
DeferredNode = NamedTuple( | ||
'DeferredNode', | ||
[ | ||
('node', Node), | ||
('node', Union[Expression, Statement, FuncItem]), | ||
('context_type_name', Optional[str]), # Name of the surrounding class (for error messages) | ||
]) | ||
|
||
|
@@ -82,9 +82,9 @@ class TypeChecker(NodeVisitor[Type]): | |
# Utility for generating messages | ||
msg = None # type: MessageBuilder | ||
# Types of type checked nodes | ||
type_map = None # type: Dict[Node, Type] | ||
type_map = None # type: Dict[Expression, Type] | ||
# Types of type checked nodes within this specific module | ||
module_type_map = None # type: Dict[Node, Type] | ||
module_type_map = None # type: Dict[Expression, Type] | ||
|
||
# Helper for managing conditional types | ||
binder = None # type: ConditionalTypeBinder | ||
|
@@ -209,15 +209,18 @@ def handle_cannot_determine_type(self, name: str, context: Context) -> None: | |
else: | ||
self.msg.cannot_determine_type(name, context) | ||
|
||
def accept(self, node: Node, type_context: Type = None) -> Type: | ||
def accept(self, node: Union[Expression, Statement, FuncItem], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not your fault (except for pointing it out :-), but it is really terrible that this takes either a syntax node or a SymbolNode. Those really aren't like each other. :-( |
||
type_context: Type = None) -> Type: | ||
"""Type check a node in the given type context.""" | ||
self.type_context.append(type_context) | ||
try: | ||
typ = node.accept(self) | ||
except Exception as err: | ||
report_internal_error(err, self.errors.file, node.line, self.errors, self.options) | ||
self.type_context.pop() | ||
self.store_type(node, typ) | ||
if typ is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explain why this check is needed? store_type() doesn't mind if typ is None, and the assert appears to be unrelated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. store_type() expects an expression, and |
||
assert isinstance(node, Expression) | ||
self.store_type(node, typ) | ||
if not self.in_checked_function(): | ||
return AnyType() | ||
else: | ||
|
@@ -1788,7 +1791,8 @@ def visit_del_stmt(self, s: DelStmt) -> Type: | |
m.line = s.line | ||
c = CallExpr(m, [e.index], [nodes.ARG_POS], [None]) | ||
c.line = s.line | ||
return c.accept(self) | ||
c.accept(self) | ||
return None | ||
else: | ||
def flatten(t: Expression) -> List[Expression]: | ||
"""Flatten a nested sequence of tuples/lists into one list of nodes.""" | ||
|
@@ -1812,7 +1816,7 @@ def visit_decorator(self, e: Decorator) -> Type: | |
if d.fullname == 'typing.no_type_check': | ||
e.var.type = AnyType() | ||
e.var.is_ready = True | ||
return NoneTyp() | ||
return None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explain? This changes the return type to Optional[Type], and that will become a problem once we turn in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my comment above. The solution has to be a separate visitor, or at least it makes sense to me. |
||
|
||
e.func.accept(self) | ||
sig = self.function_type(e.func) # type: Type | ||
|
@@ -2203,7 +2207,7 @@ def check_type_equivalency(self, t1: Type, t2: Type, node: Context, | |
if not is_equivalent(t1, t2): | ||
self.fail(msg, node) | ||
|
||
def store_type(self, node: Node, typ: Type) -> None: | ||
def store_type(self, node: Expression, typ: Type) -> None: | ||
"""Store the type of a node in the type map.""" | ||
self.type_map[node] = typ | ||
if typ is not None: | ||
|
@@ -2338,7 +2342,7 @@ def method_type(self, func: FuncBase) -> FunctionLike: | |
# probably be better to have the dict keyed by the nodes' literal_hash | ||
# field instead. | ||
|
||
TypeMap = Optional[Dict[Node, Type]] | ||
TypeMap = Optional[Dict[Expression, Type]] | ||
|
||
|
||
def conditional_type_map(expr: Expression, | ||
|
@@ -2417,7 +2421,7 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: | |
|
||
|
||
def find_isinstance_check(node: Expression, | ||
type_map: Dict[Node, Type], | ||
type_map: Dict[Expression, Type], | ||
) -> Tuple[TypeMap, TypeMap]: | ||
"""Find any isinstance checks (within a chain of ands). Includes | ||
implicit and explicit checks for None. | ||
|
@@ -2442,8 +2446,8 @@ def find_isinstance_check(node: Expression, | |
# Check for `x is None` and `x is not None`. | ||
is_not = node.operators == ['is not'] | ||
if is_not or node.operators == ['is']: | ||
if_vars = {} # type: Dict[Node, Type] | ||
else_vars = {} # type: Dict[Node, Type] | ||
if_vars = {} # type: Dict[Expression, Type] | ||
else_vars = {} # type: Dict[Expression, Type] | ||
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 | ||
|
@@ -2462,7 +2466,7 @@ def find_isinstance_check(node: Expression, | |
vartype = type_map[node] | ||
if_type = true_only(vartype) | ||
else_type = false_only(vartype) | ||
ref = node # type: Node | ||
ref = node # type: Expression | ||
if_map = {ref: if_type} if not isinstance(if_type, UninhabitedType) else None | ||
else_map = {ref: else_type} if not isinstance(else_type, UninhabitedType) else None | ||
return if_map, else_map | ||
|
@@ -2490,7 +2494,7 @@ def find_isinstance_check(node: Expression, | |
return {}, {} | ||
|
||
|
||
def get_isinstance_type(expr: Expression, type_map: Dict[Node, Type]) -> Type: | ||
def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> Type: | ||
type = type_map[expr] | ||
|
||
if isinstance(type, TupleType): | ||
|
@@ -2517,13 +2521,11 @@ def get_isinstance_type(expr: Expression, type_map: Dict[Node, Type]) -> Type: | |
return UnionType(types) | ||
|
||
|
||
def expand_node(defn: FuncItem, map: Dict[TypeVarId, Type]) -> Node: | ||
visitor = TypeTransformVisitor(map) | ||
A3E2 | return defn.accept(visitor) | |
|
||
|
||
def expand_func(defn: FuncItem, map: Dict[TypeVarId, Type]) -> FuncItem: | ||
return cast(FuncItem, expand_node(defn, map)) | ||
visitor = TypeTransformVisitor(map) | ||
ret = defn.accept(visitor) | ||
assert isinstance(ret, FuncItem) | ||
return ret | ||
|
||
|
||
class TypeTransformVisitor(TransformVisitor): | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think it can only be FuncItem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes :|
Fixed