def _infer_func_def(node, context, solver):
"""Infer the type for a function definition"""
if is_stub(node) or has_type_var(node, solver):
return_annotation = node.returns
args_annotations = []
for arg in node.args.args:
args_annotations.append(arg.annotation)
defaults_count = len(node.args.defaults)
if hasattr(node, "method_type"): # check if the node contains the manually added method flag
if node.method_type not in context.builtin_methods:
context.builtin_methods[node.method_type] = {}
context.builtin_methods[node.method_type][node.name] = AnnotatedFunction(args_annotations,
return_annotation,
defaults_count)
else:
context.set_type(node.name, AnnotatedFunction(args_annotations, return_annotation, defaults_count))
return solver.z3_types.none
func_context, args_types = _init_func_context(node, node.args.args, context, solver)
result_type = context.get_type(node.name)
result_type.args_count = len(node.args.args)
context.set_type(node.name, result_type)
context.add_func_ast(node.name, node)
if hasattr(node.args, "defaults"):
# Use the default args to infer the function parameters
_infer_args_defaults(args_types, node.args.defaults, context, solver)
defaults_len = len(node.args.defaults)
else:
defaults_len = 0
if node.returns:
return_type = solver.resolve_annotation(node.returns)
if inference_config["ignore_fully_annotated_function"] and is_annotated(node)\
or isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Ellipsis):
# Ignore the body if it has return annotation and one of the following conditions:
# The configuration flag for doing so is set
# The body begins with ellipsis
body_type = return_type
else:
body_type = _infer_body(node.body, func_context, node.lineno, solver)
solver.add(body_type == return_type,
fail_message="Return type annotation in line {}".format(node.lineno))
else:
body_type = _infer_body(node.body, func_context, node.lineno, solver)
return_type = solver.new_z3_const("return")
solver.add(solver.z3_types.subtype(body_type, return_type),
fail_message="Return type in line {}".format(node.lineno))
# Putting higher weight for this soft constraint to give it higher priority over soft-constraint
# added by inheritance covariance/contravariance return type
solver.optimize.add_soft(body_type == return_type, weight=2)
func_type = solver.z3_types.funcs[len(args_types)]((defaults_len,) + args_types + (return_type,))
solver.add(result_type == func_type,
fail_message="Function definition in line {}".format(node.lineno))
return solver.z3_types.none
评论列表
文章目录