59 current_func(nullptr),
63 python_filename_ = ast_[
"filename"].template get<std::string>();
64 if (ast_.contains(
"ast_output_dir"))
74 Json *
class_method(
const std::string &cls,
const Json &method);
79 static const std::string s =
"<unresolved>";
89 const std::pair<std::string, size_t> &
key,
90 std::set<std::string> types,
91 const std::set<std::string> &top_level_funcs);
94 std::map<std::pair<std::string, size_t>, std::set<std::string>>
96 const std::set<std::string> &top_level_funcs,
97 std::set<std::pair<std::string, size_t>> &dynamically_typed_params);
110 class_init(
const std::string &class_name,
unsigned depth,
bool &inherited);
112 std::map<Json *, std::set<std::string>> inherited_init_args_;
116 Json find_var_node_for_inference(
const std::string &var_name);
121 bool append_arg_is_plain_int(
const Json &arg);
123 find_annotated_assign(
const std::string &
node_name,
const Json &body);
125 match_unpacking_assignment(
const Json &elem,
const std::string &
node_name);
126 Json find_receiver_decl(
const std::string &obj);
128 find_function_calls(
const std::string &func_name,
const Json &body);
129 void find_function_calls_recursive(
130 const std::string &func_name,
132 std::vector<Json> &calls);
133 void get_global_elements(
const Json &node);
136 std::string get_current_func_name();
137 bool is_rebound_in_scope(
const std::string &var_name);
138 unsigned arg_type_depth_ = 0;
139 std::string get_type_from_constant(
const Json &element);
140 std::string get_type_from_lhs(
const std::string &
id,
const Json &body);
141 std::string get_list_subtype(
const Json &list);
142 std::string get_list_type_from_literal(
const Json &list_arg);
143 std::string subscript_annotation_type(
const Json &annotation);
145 container_literal_type(
const std::string &
base_type,
const Json &
value);
146 std::string list_concat_type(
const Json &binop);
154 std::string recover_list_type_from_appends(
const std::string &var_name);
155 std::string bare_list_subscript_type(
156 const Json &var_node,
157 const std::string &var_name,
159 std::string homogeneous_literal_subscript_type(
160 const Json &var_node,
161 const std::string &var_name,
164 refine_any_from_value(
const std::string &annotated,
const Json &var_node);
165 std::string get_object_name(
const Json &call,
const std::string &prefix);
166 std::string get_string_method_return_type(
const std::string &method)
const;
167 bool extract_type_info(
168 const Json &annotation,
170 std::string &element_type);
171 std::string infer_dict_value_type(
const Json &var_node);
172 std::string resolve_subscript_type(
173 const Json &subscript_node,
175 bool nested =
false);
179 std::string subscript_type_from_call(
const Json &subscript_node);
182 std::string subscript_type_from_list_literal(
const Json &subscript_node);
184 is_imported_name_in_body(
const std::string &name,
const Json &stmts)
const;
185 bool is_imported_name(
const std::string &name)
const;
186 std::string infer_unpacked_element_type(
const Json &rhs,
size_t index);
187 std::string resolve_object_class_name(
const std::string &obj);
188 std::string match_literal_argument(
189 const Json &call_node,
190 std::vector<Json> overloads)
const;
191 std::string resolve_overload_return_type(
192 const std::string &func_name,
193 const Json &call_node)
const;
196 std::string get_argument_type(
const Json &arg);
197 std::string get_dict_literal_type(
const Json &dict_value);
198 std::string get_call_type(
const Json &arg);
199 std::string get_attribute_type(
const Json &arg);
200 std::string class_attribute_type(
201 const std::string &cls,
202 const std::string &attr,
203 bool constructed_only =
false);
204 std::string self_attribute_type(
const Json &node);
205 std::string get_operand_type(
const Json &node);
206 std::string get_builtin_call_type(
const Json &call);
209 std::string arg_dependent_call_type(
const Json &call);
210 std::string list_copy_type(
const std::string &func_name,
const Json &call);
211 std::string dict_view_list_type(
const Json &call);
212 std::string get_type_from_binary_expr(
const Json &stmt,
const Json &body);
213 bool is_array_operand(
const Json &operand,
const Json &body);
214 std::string operand_annotation_type(
const Json &decl);
215 std::string get_type_from_rhs_variable(
const Json &element,
const Json &body);
216 bool holds_callable_value(
const std::string &name)
const;
217 std::string get_type_from_call(
const Json &element);
218 std::optional<std::string> get_type_from_literal_method(
const Json &call);
219 std::string get_type_from_method(
const Json &call);
220 std::string get_type_from_call_or_random(
const Json &element);
222 const Json &ifexp_node,
224 std::string &inferred_type);
225 std::optional<std::pair<Json, std::string>>
228 function_value_return_type(
const Json &
value,
const Json *call =
nullptr);
230 infer_type(
const Json &stmt,
const Json &body, std::string &inferred_type);
236 bool is_numpy_array_ctor_call(
const Json &call_value)
const;
244 bool current_func_returns_name_directly(
const std::string &name)
const;
246 get_function_return_type(
const std::string &func_name,
const Json &ast);
247 std::string infer_lambda_return_type(
const Json &lambda_elem)
const;
249 std::string infer_from_return_statements(
251 const std::string &func_name,
252 bool *divergent =
nullptr);
254 std::string infer_type_from_parameter_default(
255 const Json &function_element,
262 method_return_type(
const Json &member,
const std::string &class_name);
266 infer_method_return_type(
const Json &member,
const std::string &class_name);
267 void collect_return_types(
269 const std::string &func_name,
270 std::set<std::string> &types);
275 expr_calls_function(
const Json &node,
const std::string &func_name);
278 static bool arithmetic_reads_attribute(
const Json &node);
281 Json create_name_annotation(
282 const std::string &type_id,
287 Json create_subscript_annotation(
289 const std::string &element_type,
296 Json create_tuple_subscript_annotation(
297 const std::vector<std::string> &elem_types,
301 Json create_annotation_from_type(
302 const std::string &inferred_type,
306 void update_assignment_node(Json &element,
const std::string &inferred_type);
307 void add_parameter_annotation(Json ¶m,
const std::string &type);
308 void update_end_col_offset(Json &ast);
311 bool are_all_user_classes(
const std::vector<std::string> &types)
const;
312 bool are_specializable_types(
const std::vector<std::string> &types)
const;
313 bool is_specialization_pending(
314 const std::string &func_name,
316 const std::vector<std::string> &types)
const;
317 std::string build_specialized_function_name(
318 const std::string &base_name,
319 const std::string &class_name)
const;
321 resolve_name_assigned_class(
const std::string &name,
const Json &node);
322 void rewrite_specialized_calls(
323 const std::string &original_name,
325 const std::unordered_map<std::string, std::string> &specialized_names,
327 void apply_pending_specializations();
331 std::vector<std::string> get_class_ancestors(
const std::string &class_name);
335 find_common_ancestor(
const std::string &type_a,
const std::string &type_b);
338 std::vector<std::string>
339 infer_subscript_key_tuple_types(
const std::string &class_name);
340 void collect_class_instance_map(
342 std::unordered_map<std::string, std::string> &out)
const;
343 template <
typename Visitor>
344 void visit_class_tuple_subscripts(
346 const std::string &class_name,
347 const std::unordered_map<std::string, std::string> &var_to_class,
349 const Json *enclosing_func =
nullptr);
350 std::string resolve_name_in_enclosing_func(
351 const std::string &name,
352 const Json &enclosing_func);
353 std::string resolve_wildcard_import_func(
const std::string &func_name);
358 bool reads_import(
const std::string &name,
const Json &use)
const;
360 resolve_expr_in_enclosing_func(
const Json &elt,
const Json &enclosing_func);
361 std::vector<std::string> infer_tuple_element_types(
363 const Json *enclosing_func =
nullptr);
366 std::vector<std::string> collect_parameter_types_from_calls(
368 const std::vector<Json> &function_calls);
369 std::vector<std::string> infer_tuple_param_types_from_calls(
371 const std::vector<Json> &function_calls);
372 std::string infer_parameter_type_from_calls(
374 const std::vector<Json> &function_calls);
379 std::string class_prefix;
380 bool in_lambda =
false;
382 std::string caller_arg_type(
const Json &arg,
const caller_scopet &scope);
383 void collect_caller_arg_types(
384 const std::string &callee,
387 const caller_scopet &scope,
388 std::vector<std::string> &types);
389 std::vector<std::string> caller_arg_types(
390 const std::string &func_name,
392 const Json &search_context);
393 std::string infer_parameter_type_at_call_sites(
394 const std::string &func_name,
396 const std::vector<Json> &function_calls,
397 const Json &search_context);
398 bool specializable_at_call_sites(
399 const std::string &func_name,
401 std::vector<std::string> &call_types,
402 const Json &search_context);
403 void infer_parameter_types(Json &function_element);
406 void annotate_global_scope();
407 void annotate_function(Json &function_element);
408 void annotate_class(Json &class_element);
409 void infer_loop_variable_types(Json &while_stmt,
bool synthesized_only);
410 Json list_element_annotation(
const Json &iter_node);
411 Json self_attr_list_element(
const std::string &attr);
412 void annotate_branch_blocks(Json &element);
413 void add_annotation(Json &body);
414 std::string widen_to_optional_scalar(
416 const std::string &inferred_type);
417 std::string optional_scalar_of(
const std::string &name,
const Json &scope);
418 std::string returned_optional_scalar(
const Json &
function,
const Json &body);
419 void collect_name_stores(
420 const std::string &name,
422 std::vector<const Json *> &stores);
427 std::shared_ptr<module_manager> module_manager_;
432 std::string python_filename_;
433 bool filter_global_elements_ =
false;
440 bool annotating_function_entry_point_ =
false;
441 std::vector<Json> referenced_global_elements;
442 std::set<std::string> functions_in_analysis_;
446 std::set<std::string> functions_reentered_;
447 std::set<std::string> resolving_rhs_vars_;
450 std::map<std::pair<const Json *, std::string>, std::string>
451 optional_scalar_names_;
452 std::string current_func_name_context_;
453 std::string current_class_name_;
454 struct pending_specializationt
456 std::string function_name;
458 std::vector<std::string> class_types;
460 std::vector<pending_specializationt> pending_specializations_;
461 void retype_builtin_copy(
463 const pending_specializationt &spec,
464 const std::string &type,
465 const std::vector<Json> &calls);
466 std::vector<const Json *> extra_subscript_inference_asts_;