// Copyright (C) 2020-2025 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . #include "rust-hir-dump.h" #include "rust-abi.h" #include "rust-hir-item.h" #include "rust-hir-path.h" #include "rust-hir-type.h" #include "rust-hir.h" #include #include "rust-attribute-values.h" namespace Rust { namespace HIR { // Dump Format for HIR // // SomeHIRNode [ // field: ... // field: ... // field: ... // ] // // When a field is a collection of other HIR objects: // field { // SomeHIRNode [ ... ] // SomeOtherHIRNode [ ... ] // } // // If a field is an empty collection: // field: empty // // If a field is optional and is currently not holding anything: // field: none std::string Dump::delims[2][2] = { {std::string ("{"), std::string ("}")}, {std::string ("["), std::string ("]")}, }; static std::string BoundPolarityString (BoundPolarity polarity) { switch (polarity) { case RegularBound: return "regular"; case NegativeBound: return "negative"; case AntiBound: return "anti"; } return "unknown"; } /** * Static member used to dump HIR from the debugger to stderr. * * @param v The HIR node to dump */ void Dump::debug (FullVisitable &v) { Dump dump (std::cerr); v.accept_vis (dump); } void Dump::go (HIR::Crate &e) { begin ("Crate"); do_inner_attrs (e); do_mappings (e.get_mappings ()); visit_collection ("items", e.get_items ()); end ("Crate"); } Dump::Dump (std::ostream &stream) : stream (stream) {} /** * Writes TEXT with a final newline if ENDLINE is true. * If TEXT is starting the current line, its first line is indented. * If TEXT is multiline, all followning lines are also indented. * * @param text Text to emit * @param endline If true, newline is emitted after text */ void Dump::put (std::string text, bool endline) { if (beg_of_line) { stream << indentation; beg_of_line = false; } // keep multiline string indented std::string::size_type pos = 0; std::string::size_type prev = 0; auto first = true; while ((pos = text.find ('\n', prev)) != std::string::npos) { if (!first) stream << std::endl << indentation; first = false; stream << text.substr (prev, pos - prev); prev = pos + 1; } if (first) stream << text; if (endline) { stream << std::endl; beg_of_line = endline; } } /** * Called when starting to emit info for an HIR node. * Emits NAME and an opening delimiter denoted by D. * * @param name Name of HIR node * @param d Delimiter */ void Dump::begin (std::string name, enum delim d) { if (!beg_of_line) put (""); put (name + " " + delims[d][0], true); indentation.increment (); } /** * Called when ending the dump info for an HIR node. Emits a C++-style * comment with NAME and a closing delimiter denoted by D. * * @param name Name of HIR node * @param d Delimiter */ void Dump::end (std::string name, enum delim d) { indentation.decrement (); if (!beg_of_line) stream << std::endl; put (delims[d][1] + " // " + name); } /** * Called when starting to emit info for a field within an HIR node. * Emits NAME and an opening curly brace * * @param name HIR field name */ void Dump::begin_field (std::string name) { begin (name, CURLY); } /** * Called when ending the dump info for a field within an HIR node. * Emits a C++-style comment with NAME and a closing curly brace * * @param name HIR field name */ void Dump::end_field (std::string name) { end (name, CURLY); } /** * Emits a single field/value pair denoted by NAME and TEXT. * * @param name Field name * @param text Field value */ void Dump::put_field (std::string name, std::string text) { put (name + ": ", false); indentation.increment (); put (text); indentation.decrement (); } /** * Recursively visits an HIR field NAME with value possibly pointed to by * PTR, if PTR is not null. If PTR is null, simply emits FIELD_NAME/NULL pair. * * @param name Field name * @param ptr Pointer to field's value */ template void Dump::visit_field (std::string name, std::unique_ptr &ptr) { if (ptr) visit_field (name, *ptr); else put_field (name, "NULL"); } /** * Recursively visits an HIR field NAME with value V. * * @param name Field name * @param v Field value */ void Dump::visit_field (std::string name, FullVisitable &v) { put (name + ": ", false); indentation.increment (); v.accept_vis (*this); indentation.decrement (); } /** * Recursively visits a collection VEC of HIR node for field NAME. * If VEC is empty, simply emits the NAME/empty pair. * * @param name Field name * @param vec Field value as a vector */ template void Dump::visit_collection (std::string name, std::vector> &vec) { if (vec.empty ()) { put_field (name, "empty"); return; } begin_field (name); for (const auto &elt : vec) elt->accept_vis (*this); end_field (name); } /** * Recursively visits a collection VEC of HIR node for field NAME. * If VEC is empty, simply emits the NAME/empty pair. * * @param name Field name * @param vec Field value as a vector */ template void Dump::visit_collection (std::string name, std::vector &vec) { if (vec.empty ()) { put_field (name, "empty"); return; } begin_field (name); for (auto &elt : vec) elt.accept_vis (*this); end_field (name); } void Dump::do_traititem (TraitItem &e) { do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); } void Dump::do_vis_item (VisItem &e) { do_item (e); std::string str = "none"; if (e.has_visibility ()) str = e.get_visibility ().as_string (); put_field ("visibility", str); } void Dump::do_functionparam (FunctionParam &e) { begin ("FunctionParam"); do_mappings (e.get_mappings ()); visit_field ("param_name", e.get_param_name ()); visit_field ("type", e.get_type ()); end ("FunctionParam"); } void Dump::do_pathpattern (PathPattern &e) { std::string str = ""; for (const auto &segment : e.get_segments ()) str += segment.as_string () + ", "; put_field ("segments", str); } void Dump::do_structexprstruct (StructExprStruct &e) { do_expr (e); // StructExpr visit_field ("struct_name", e.get_struct_name ()); // StructExprStruct do_mappings (e.get_mappings ()); do_inner_attrs (e); } void Dump::do_ifexpr (IfExpr &e) { do_expr (e); visit_field ("condition", e.get_if_condition ()); visit_field ("if_block", e.get_if_block ()); } void Dump::do_expr (Expr &e) { do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); } void Dump::do_pathexpr (PathExpr &e) { do_expr (e); } void Dump::do_typepathsegment (TypePathSegment &e) { do_mappings (e.get_mappings ()); put_field ("ident_segment", e.get_ident_segment ().as_string ()); } void Dump::do_typepathfunction (TypePathFunction &e) { visit_collection ("params", e.get_params ()); visit_field ("return_type", e.get_return_type ()); } void Dump::do_qualifiedpathtype (QualifiedPathType &e) { do_mappings (e.get_mappings ()); visit_field ("type", e.get_type ()); visit_field ("trait", e.get_trait ()); } void Dump::do_operatorexpr (OperatorExpr &e) { visit_field ("main_or_left_expr", e.get_expr ()); } void Dump::do_mappings (const Analysis::NodeMapping &mappings) { put ("mapping: ", false); put (mappings.as_string ()); } void Dump::do_inner_attrs (WithInnerAttrs &e) { auto attrs = e.get_inner_attrs (); if (attrs.empty ()) { put_field ("inner_attrs", "empty"); return; } begin_field ("inner_attrs"); for (auto &elt : attrs) visit (elt); end_field ("inner_attrs"); } void Dump::do_outer_attrs (std::vector &attrs) { if (attrs.empty ()) put_field ("outer_attributes", "empty"); else { begin_field ("outer_attributes"); for (const auto &attr : attrs) put (attr.as_string ()); end_field ("outer_attributes"); } } void Dump::do_baseloopexpr (BaseLoopExpr &e) { do_expr (e); if (!e.has_loop_label ()) put_field ("label", "none"); else put_field ("label", e.get_loop_label ().as_string ()); visit_field ("loop_block", e.get_loop_block ()); } void Dump::do_ifletexpr (IfLetExpr &e) { do_expr (e); visit_collection ("match_arm_patterns", e.get_patterns ()); visit_field ("value", e.get_scrutinee_expr ()); visit_field ("if_block", e.get_if_block ()); } void Dump::do_struct (Struct &e) { do_vis_item (e); put_field ("struct_name", e.get_identifier ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); if (!e.has_where_clause ()) put_field ("where_clause", "none"); else put_field ("where clause", e.get_where_clause ().as_string ()); } void Dump::do_enumitem (EnumItem &e) { do_item (e); put_field ("variant_name", e.get_identifier ().as_string ()); std::string str; switch (e.get_enum_item_kind ()) { case EnumItem::EnumItemKind::Named: str = "[Named variant]"; break; case EnumItem::EnumItemKind::Tuple: str = "[Tuple variant]"; break; case EnumItem::EnumItemKind::Struct: str = "[Struct variant]"; break; case EnumItem::EnumItemKind::Discriminant: str = "[Discriminant variant]"; break; } put_field ("item_kind", str); } void Dump::do_traitfunctiondecl (TraitFunctionDecl &e) { begin ("TraitFunctionDecl"); put_field ("qualifiers", e.get_qualifiers ().as_string ()); put_field ("function_name", e.get_function_name ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); if (!e.get_function_params ().empty ()) { begin_field ("function_params"); for (auto &item : e.get_function_params ()) do_functionparam (item); end_field ("function_params"); } else put_field ("function_params", "empty"); visit_field ("return_type", e.get_return_type ()); if (e.has_where_clause ()) put_field ("where_clause", e.get_where_clause ().as_string ()); else put_field ("where_clause", "none"); put_field ("self", e.get_self ().as_string ()); end ("TraitFunctionDecl"); } void Dump::do_externalitem (ExternalItem &e) { do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); std::string str = "none"; if (e.has_visibility ()) str = e.get_visibility ().as_string (); put_field ("visibility", str); put_field ("item_name", e.get_item_name ().as_string ()); } void Dump::do_namefunctionparam (NamedFunctionParam &e) { begin ("NamedFunctionParam"); do_mappings (e.get_mappings ()); put_field ("name", e.get_param_name ().as_string ()); visit_field ("type", e.get_type ()); end ("NamedFunctionParam"); } void Dump::do_stmt (Stmt &e) { do_mappings (e.get_mappings ()); } void Dump::do_type (Type &e) { do_mappings (e.get_mappings ()); } void Dump::do_item (Item &e) { do_stmt (e); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); } void Dump::do_tuplefield (TupleField &e) { do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); std::string str = "none"; if (e.has_visibility ()) str = e.get_visibility ().as_string (); put_field ("visibility", str); visit_field ("field_type", e.get_field_type ()); } void Dump::do_structfield (StructField &e) { do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); std::string str = "none"; if (e.has_visibility ()) str = e.get_visibility ().as_string (); put_field ("visibility", str); put_field ("field_name", e.get_field_name ().as_string ()); visit_field ("field_type", e.get_field_type ()); } void Dump::do_genericargs (GenericArgs &e) { visit_collection ("lifetime_args", e.get_lifetime_args ()); visit_collection ("type_args", e.get_type_args ()); if (e.get_const_args ().empty ()) { put_field ("binding_args", "empty"); } else { begin_field ("const_args"); for (auto &arg : e.get_const_args ()) { begin ("ConstGenericArg"); visit_field ("expression", arg.get_expression ()); end ("ConstGenericArg"); } end_field ("const_args"); } if (e.get_binding_args ().empty ()) { put_field ("binding_args", "empty"); } else { begin_field ("binding_args"); for (auto &arg : e.get_binding_args ()) { begin ("GenericArgsBinding"); put_field ("identfier", arg.get_identifier ().as_string ()); visit_field ("type", arg.get_type ()); end ("GenericArgsBinding"); } end_field ("binding_args"); } } void Dump::do_maybenamedparam (MaybeNamedParam &e) { visit_field ("param_type", e.get_type ()); put_field ("param_kind", enum_to_str (e.get_param_kind ())); put_field ("name", e.get_name ().as_string ()); } // All visit methods void Dump::visit (AST::Attribute &attribute) { // Special, no begin/end as this is called by do_inner_attrs. put_field (Values::Attributes::PATH, attribute.get_path ().as_string ()); std::string str = "none"; if (attribute.has_attr_input ()) str = attribute.get_attr_input ().as_string (); put_field ("attr_input", str); } void Dump::visit (Lifetime &e) { do_mappings (e.get_mappings ()); std::string type; std::string name = e.get_name (); switch (e.get_lifetime_type ()) { case AST::Lifetime::LifetimeType::NAMED: type = "[NAMED]"; break; case AST::Lifetime::LifetimeType::STATIC: type = "[STATIC]"; name += " (not applicable for type)"; break; case AST::Lifetime::LifetimeType::WILDCARD: type = "[WILDCARD]"; name += " (not applicable for type)"; break; default: rust_assert (false); break; } put_field ("lifetime_type", type); put_field ("lifetime_name", name); } void Dump::visit (LifetimeParam &lifetimeparam) { begin ("Lifetimeparam"); put (lifetimeparam.as_string ()); end ("Lifetimeparam"); } void Dump::visit (PathInExpression &e) { begin ("PathInExpression"); do_pathpattern (e); do_pathexpr (e); put_field ("has_opening_scope_resolution", std::to_string (e.opening_scope_resolution ())); end ("PathInExpression"); } void Dump::visit (TypePathSegment &e) { begin ("TypePathSegment"); do_typepathsegment (e); end ("TypePathSegment"); } void Dump::visit (TypePathSegmentGeneric &e) { begin ("TypePathSegmentGeneric"); do_typepathsegment (e); if (e.has_generic_args ()) { begin_field ("generic_args"); begin ("GenericArgs"); do_genericargs (e.get_generic_args ()); end ("GenericArgs"); end_field ("generic_args"); } else { put_field ("generic_args", "empty"); } end ("TypePathSegmentGeneric"); } void Dump::visit (TypePathSegmentFunction &e) { begin ("TypePathSegmentFunction"); do_typepathsegment (e); begin ("function_path"); do_typepathfunction (e.get_function_path ()); end ("function_path"); end ("TypePathSegmentFunction"); } void Dump::visit (TypePath &e) { begin ("TypePath"); put_field ("has_opening_scope_resolution", std::to_string (e.has_opening_scope_resolution_op ())); visit_collection ("segments", e.get_segments ()); end ("TypePath"); } void Dump::visit (QualifiedPathInExpression &e) { begin ("QualifiedPathInExpression"); do_pathpattern (e); do_expr (e); begin_field ("path_type"); begin ("QualifiedPathType"); do_qualifiedpathtype (e.get_path_type ()); end ("QualifiedPathType"); end_field ("path_type"); end ("QualifiedPathInExpression"); } void Dump::visit (QualifiedPathInType &e) { begin ("QualifiedPathInType"); begin_field ("path_type"); do_qualifiedpathtype (e.get_path_type ()); end_field ("path_type"); begin_field ("associated_segment"); do_typepathsegment (*e.get_associated_segment ()); end_field ("associated_segment"); visit_collection ("segments", e.get_segments ()); end ("QualifiedPathInType"); } void Dump::visit (LiteralExpr &e) { begin ("LiteralExpr"); do_expr (e); put_field ("literal", e.get_literal ().as_string ()); end ("LiteralExpr"); } void Dump::visit (BorrowExpr &e) { begin ("BorrowExpr"); do_operatorexpr (e); put_field ("mut", enum_to_str (e.get_mut ())); end ("BorrowExpr"); } void Dump::visit (DereferenceExpr &e) { begin ("DereferenceExpr"); do_operatorexpr (e); end ("DereferenceExpr"); } void Dump::visit (ErrorPropagationExpr &e) { begin ("ErrorPropagationExpr"); do_operatorexpr (e); end ("ErrorPropagationExpr"); } void Dump::visit (NegationExpr &e) { begin ("NegationExpr"); do_operatorexpr (e); std::string str; switch (e.get_expr_type ()) { case NegationOperator::NEGATE: str = "[NEGATE]"; break; case NegationOperator::NOT: str = "[NOT]"; break; default: rust_assert (false); } put_field ("expr_type", str); end ("NegationExpr"); } void Dump::visit (ArithmeticOrLogicalExpr &e) { begin ("ArithmeticOrLogicalExpr"); std::string str; // which operator switch (e.get_expr_type ()) { case ArithmeticOrLogicalOperator::ADD: str = "[ADD]"; break; case ArithmeticOrLogicalOperator::SUBTRACT: str = "SUBTRACT"; break; case ArithmeticOrLogicalOperator::MULTIPLY: str = "MULTIPLY"; break; case ArithmeticOrLogicalOperator::DIVIDE: str = "DIVIDE"; break; case ArithmeticOrLogicalOperator::MODULUS: str = "MODULUS"; break; case ArithmeticOrLogicalOperator::BITWISE_AND: str = "BITWISE"; break; case ArithmeticOrLogicalOperator::BITWISE_OR: str = "BITWISE"; break; case ArithmeticOrLogicalOperator::BITWISE_XOR: str = "BITWISE"; break; case ArithmeticOrLogicalOperator::LEFT_SHIFT: str = "as_string ()); end ("StructExprStructFields"); } void Dump::visit (StructExprStructBase &e) { begin ("StructExprStructBase"); do_structexprstruct (e); put_field ("struct_base", e.get_struct_base ()->as_string ()); end ("StructExprStructBase"); } void Dump::visit (CallExpr &e) { begin ("CallExpr"); do_expr (e); visit_field ("function", e.get_fnexpr ()); visit_collection ("params", e.get_arguments ()); end ("CallExpr"); } void Dump::visit (MethodCallExpr &e) { begin ("MethodCallExpr"); do_expr (e); visit_field ("receiver", e.get_receiver ()); put_field ("method_name", e.get_method_name ().as_string ()); visit_collection ("params", e.get_arguments ()); end ("MethodCallExpr"); } void Dump::visit (FieldAccessExpr &e) { begin ("FieldAccessExpr"); do_expr (e); visit_field ("receiver", e.get_receiver_expr ()); put_field ("field", e.get_field_name ().as_string ()); end ("FieldAccessExpr"); } void Dump::visit (ClosureExpr &e) { begin ("ClosureExpr"); do_expr (e); if (!e.has_params ()) { put_field ("params", "none"); } else { begin_field ("params"); for (auto ¶m : e.get_params ()) { begin ("ClosureParam"); auto oa = param.get_outer_attrs (); do_outer_attrs (oa); visit_field ("pattern", param.get_pattern ()); visit_field ("type", param.get_type ()); end ("ClosureParam"); } end_field ("params"); } visit_field ("return_type", e.get_return_type ()); visit_field ("expr", e.get_expr ()); end ("ClosureExpr"); } void Dump::visit (BlockExpr &e) { begin ("BlockExpr"); do_expr (e); do_inner_attrs (e); visit_collection ("statements", e.get_statements ()); visit_field ("expr", e.get_final_expr ()); end ("BlockExpr"); } void Dump::visit (ContinueExpr &e) { begin ("ContinueExpr"); if (e.has_label ()) put_field ("label", e.get_label ().as_string ()); else put_field ("label", "none"); end ("ContinueExpr"); } void Dump::visit (BreakExpr &e) { begin ("BreakExpr"); std::string str ("break "); if (e.has_label ()) put_field ("label", e.get_label ().as_string ()); else put_field ("label", "none"); visit_field ("break_expr ", e.get_expr ()); end ("BreakExpr"); } void Dump::visit (RangeFromToExpr &e) { begin ("RangeFromToExpr"); visit_field ("from", e.get_from_expr ()); visit_field ("to", e.get_to_expr ()); end ("RangeFromToExpr"); } void Dump::visit (RangeFromExpr &e) { begin ("RangeFromExpr"); visit_field ("from", e.get_from_expr ()); end ("RangeFromExpr"); } void Dump::visit (RangeToExpr &e) { begin ("RangeToExpr"); visit_field ("to", e.get_to_expr ()); end ("RangeToExpr"); } void Dump::visit (RangeFullExpr &e) { begin ("RangeFullExpr"); end ("RangeFullExpr"); } void Dump::visit (RangeFromToInclExpr &e) { begin ("RangeFromToInclExpr"); visit_field ("from", e.get_from_expr ()); visit_field ("to", e.get_to_expr ()); end ("RangeFromToInclExpr"); } void Dump::visit (RangeToInclExpr &e) { begin ("RangeToInclExpr"); visit_field ("to", e.get_to_expr ()); end ("RangeToInclExpr"); } void Dump::visit (ReturnExpr &e) { begin ("ReturnExpr"); do_mappings (e.get_mappings ()); visit_field ("return_expr", e.get_expr ()); end ("ReturnExpr"); } void Dump::visit (UnsafeBlockExpr &e) { begin ("UnsafeBlockExpr"); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); visit_field ("block_expr", e.get_block_expr ()); end ("UnsafeBlockExpr"); } void Dump::visit (LoopExpr &e) { begin ("LoopExpr"); do_baseloopexpr (e); end ("LoopExpr"); } void Dump::visit (WhileLoopExpr &e) { begin ("WhileLoopExpr"); do_baseloopexpr (e); visit_field ("condition", e.get_predicate_expr ()); end ("WhileLoopExpr"); } void Dump::visit (WhileLetLoopExpr &e) { begin ("WhileLetLoopExpr"); do_baseloopexpr (e); visit_collection ("match_arm_patterns", e.get_patterns ()); visit_field ("condition", e.get_cond ()); end ("WhileLetLoopExpr"); } void Dump::visit (IfExpr &e) { begin ("IfExpr"); do_ifexpr (e); end ("IfExpr"); } void Dump::visit (IfExprConseqElse &e) { begin ("IfExprConseqElse"); do_ifexpr (e); visit_field ("else_block", e.get_else_block ()); end ("IfExprConseqElse"); } void Dump::visit (IfLetExpr &e) { begin ("IfLetExpr"); do_ifletexpr (e); end ("IfLetExpr"); } void Dump::visit (IfLetExprConseqElse &e) { begin ("IfLetExprConseqElse"); do_ifletexpr (e); visit_field ("else_block", e.get_else_block ()); end ("IfLetExprConseqElse"); } void Dump::visit (MatchExpr &e) { begin ("MatchExpr"); do_inner_attrs (e); do_expr (e); visit_field ("branch_value", e.get_scrutinee_expr ()); std::string str; if (e.get_match_cases ().empty ()) str = "none"; else for (const auto &arm : e.get_match_cases ()) str += "\n " + arm.as_string (); put_field ("match_arms", str); end ("MatchExpr"); } void Dump::visit (AwaitExpr &e) { begin ("AwaitExpr"); do_expr (e); visit_field ("awaited_expr", e.get_awaited_expr ()); end ("AwaitExpr"); } void Dump::visit (AsyncBlockExpr &e) { begin ("AsyncBlockExpr"); do_expr (e); put_field ("has move", std::to_string (e.get_has_move ())); visit_field ("block_expr", e.get_block_expr ()); end ("AsyncBlockExpr"); } void Dump::visit (TypeParam &e) { begin ("TypeParam"); put_field ("outer_attr", e.get_outer_attribute ().as_string ()); put_field ("type_representation", e.get_type_representation ().as_string ()); visit_collection ("type_param_bounds", e.get_type_param_bounds ()); visit_field ("type", e.get_type ()); end ("TypeParam"); } void Dump::visit (ConstGenericParam &e) { begin ("ConstGenericParam"); do_mappings (e.get_mappings ()); put_field ("name", e.get_name ()); visit_field ("type", e.get_type ()); visit_field ("default_expression", e.get_default_expression ()); end ("ConstGenericParam"); } void Dump::visit (LifetimeWhereClauseItem &e) { begin ("LifetimeWhereClauseItem"); do_mappings (e.get_mappings ()); visit_field ("lifetime", e.get_lifetime ()); visit_collection ("lifetime_bounds", e.get_lifetime_bounds ()); end ("LifetimeWhereClauseItem"); } void Dump::visit (TypeBoundWhereClauseItem &e) { begin ("TypeBoundWhereClauseItem"); do_mappings (e.get_mappings ()); visit_collection ("for_lifetime", e.get_for_lifetimes ()); visit_field ("bound_type", e.get_bound_type ()); visit_collection ("type_param_bound", e.get_type_param_bounds ()); end ("TypeBoundWhereClauseItem"); } void Dump::visit (Module &e) { begin ("Module"); do_inner_attrs (e); put_field ("module_name", e.get_module_name ().as_string ()); visit_collection ("items", e.get_items ()); end ("Module"); } void Dump::visit (ExternCrate &e) { begin ("ExternCrate"); do_vis_item (e); put_field ("referenced_crate", e.get_referenced_crate ()); put_field ("as_clause_name", e.get_as_clause_name ()); end ("ExternCrate"); } void Dump::visit (UseTreeGlob &e) { begin ("UseTreeGlob"); std::string glob, path = "not applicable"; switch (e.get_glob_type ()) { case UseTreeGlob::PathType::NO_PATH: glob = "*"; break; case UseTreeGlob::PathType::GLOBAL: glob = "::*"; break; case UseTreeGlob::PathType::PATH_PREFIXED: { path = e.get_path ().as_string (); glob = "::*"; break; } default: gcc_unreachable (); } put_field ("glob", glob); put_field ("path", path); end ("UseTreeGlob"); } void Dump::visit (UseTreeList &e) { begin ("UseTreeList"); std::string path_type, path = "not applicable"; switch (e.get_path_type ()) { case UseTreeList::PathType::NO_PATH: path_type = "*"; break; case UseTreeList::PathType::GLOBAL: path_type = "::*"; break; case UseTreeList::PathType::PATH_PREFIXED: { path = e.get_path ().as_string (); path_type = "::*"; break; } default: gcc_unreachable (); } put_field ("path_type", path_type); put_field ("path", path); visit_collection ("trees", e.get_trees ()); end ("UseTreeList"); } void Dump::visit (UseTreeRebind &e) { begin ("UseTreeRebind"); put_field ("path", e.get_path ().as_string ()); put_field ("identifier", e.get_identifier ().as_string ()); put_field ("bind_type", enum_to_str (e.get_bind_type ())); end ("UseTreeRebind"); } void Dump::visit (UseDeclaration &e) { begin ("UseDeclaration"); do_vis_item (e); visit_field ("use_tree", e.get_use_tree ()); end ("UseDeclaration"); } void Dump::visit (Function &e) { begin ("Function"); do_vis_item (e); put_field ("function_qualifiers", e.get_qualifiers ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); put_field ("function_name", e.get_function_name ().as_string ()); if (e.has_function_params ()) { begin_field ("function_params"); for (auto &item : e.get_function_params ()) do_functionparam (item); end_field ("function_params"); } else { put_field ("function_params", "empty"); } visit_field ("return_type", e.get_return_type ()); if (!e.has_where_clause ()) put_field ("where_clause", "none"); else put_field ("where clause", e.get_where_clause ().as_string ()); visit_field ("function_body", e.get_definition ()); put_field ("self", e.get_self_param ().as_string ()); end ("Function"); } void Dump::visit (TypeAlias &e) { begin ("TypeAlias"); do_vis_item (e); put_field ("new_type_name", e.get_new_type_name ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); if (!e.has_where_clause ()) put_field ("where_clause", "none"); else put_field ("where clause", e.get_where_clause ().as_string ()); put_field ("type", e.get_type_aliased ()->as_string ()); end ("TypeAlias"); } void Dump::visit (StructStruct &e) { begin ("StructStruct"); do_struct (e); put_field ("is_unit", std::to_string (e.is_unit_struct ())); if (e.get_fields ().empty ()) put_field ("fields", "empty"); else { begin_field ("fields"); for (auto &field : e.get_fields ()) { begin ("StructField"); do_structfield (field); end ("StructField"); } end_field ("fields"); } end ("StructStruct"); } void Dump::visit (TupleStruct &e) { begin ("TupleStruct"); do_struct (e); if (e.get_fields ().empty ()) put_field ("fields", "empty"); else { begin_field ("fields"); for (auto &field : e.get_fields ()) { begin ("TupleField"); do_tuplefield (field); end ("TupleField"); } end_field ("fields"); } end ("TupleStruct"); } void Dump::visit (EnumItem &e) { begin ("EnumItem"); do_enumitem (e); end ("EnumItem"); } void Dump::visit (EnumItemTuple &e) { begin ("EnumItemTuple"); do_enumitem (e); if (e.has_tuple_fields ()) { begin_field ("tuple_fields"); for (auto field : e.get_tuple_fields ()) do_tuplefield (field); end_field ("tuple_fields"); } else put_field ("tuple_fields", "empty"); end ("EnumItemTuple"); } void Dump::visit (EnumItemStruct &e) { begin ("EnumItemStruct"); do_enumitem (e); if (e.has_struct_fields ()) { begin_field ("struct_fields"); for (auto field : e.get_struct_fields ()) do_structfield (field); end_field ("struct_fields"); } else { put_field ("struct_fields", "empty"); } end ("EnumItemStruct"); } void Dump::visit (EnumItemDiscriminant &e) { begin ("EnumItemDiscriminant"); do_enumitem (e); visit_field ("discriminant", e.get_discriminant_expression ()); end ("EnumItemDiscriminant"); } void Dump::visit (Enum &e) { begin ("Enum"); do_vis_item (e); put_field ("enum_name", e.get_identifier ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); std::string str = "none"; if (e.has_where_clause ()) str = e.get_where_clause ().as_string (); put_field ("where clause", str); visit_collection ("items", e.get_variants ()); end ("Enum"); } void Dump::visit (Union &e) { begin ("Union"); do_vis_item (e); visit_collection ("generic_params", e.get_generic_params ()); std::string str; if (e.has_where_clause ()) str = e.get_where_clause ().as_string (); else str = "none"; put_field ("where clause", str); if (e.get_variants ().empty ()) { put_field ("variants", "empty"); } else { begin_field ("variants"); for (auto &elt : e.get_variants ()) { begin ("StructField"); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); std::string str = "none"; if (elt.has_visibility ()) str = elt.get_visibility ().as_string (); put_field ("visibility", str); put_field ("field_name", elt.get_field_name ().as_string ()); visit_field ("field_type", elt.get_field_type ()); end ("StructField"); } end_field ("variants"); } end ("Union"); } void Dump::visit (ConstantItem &e) { begin ("ConstantItem"); do_vis_item (e); put_field ("identifier", e.get_identifier ().as_string ()); visit_field ("type", e.get_type ()); visit_field ("const_expr", e.get_expr ()); end ("ConstantItem"); } void Dump::visit (StaticItem &e) { begin ("StaticItem"); do_vis_item (e); put_field ("mut", std::to_string (e.is_mut ())); put_field ("name", e.get_identifier ().as_string ()); visit_field ("type", e.get_type ()); visit_field ("expr", e.get_expr ()); end ("StaticItem"); } void Dump::visit (TraitItemFunc &e) { begin ("TraitItemFunc"); do_traititem (e); do_traitfunctiondecl (e.get_decl ()); visit_field ("block_expr", e.get_block_expr ()); end ("TraitItemFunc"); } void Dump::visit (TraitItemConst &e) { begin ("TraitItemConst"); do_traititem (e); put_field ("name", e.get_name ().as_string ()); visit_field ("type", e.get_type ()); visit_field ("expr", e.get_expr ()); end ("TraitItemConst"); } void Dump::visit (TraitItemType &e) { begin ("TraitItemType"); do_traititem (e); put_field ("name", e.get_name ().as_string ()); visit_collection ("type_param_bounds", e.get_type_param_bounds ()); end ("TraitItemType"); } void Dump::visit (Trait &e) { begin ("Trait"); do_vis_item (e); put_field ("unsafety", std::to_string (e.is_unsafe ())); put_field ("name", e.get_name ().as_string ()); visit_collection ("generic_params", e.get_generic_params ()); visit_collection ("type_param_bounds", e.get_type_param_bounds ()); std::string str; if (e.has_where_clause ()) str = e.get_where_clause ().as_string (); else str = "none"; put_field ("where clause", str); visit_collection ("trait_items", e.get_trait_items ()); end ("Trait"); } void Dump::visit (ImplBlock &e) { begin ("ImplBlock"); do_vis_item (e); visit_collection ("generic_params", e.get_generic_params ()); visit_field ("impl_type", e.get_type ()); std::string str; if (e.has_where_clause ()) str = e.get_where_clause ().as_string (); else str = "none"; put_field ("where clause", str); do_inner_attrs (e); visit_collection ("impl_items", e.get_impl_items ()); end ("ImplBlock"); } void Dump::visit (ExternalStaticItem &e) { begin ("ExternalStaticItem"); // FIXME do_vis_item... but not a VisItem... But could be? auto oa = e.get_outer_attrs (); do_outer_attrs (oa); std::string str = "none"; if (e.has_visibility ()) str = e.get_visibility ().as_string (); put_field ("visibility", str); // put_field ("mut", std::to_string (e.is_mut ())); put_field ("name", e.get_item_name ().as_string ()); visit_field ("type", e.get_item_type ()); end ("ExternalStaticItem"); } void Dump::visit (ExternalFunctionItem &e) { begin ("ExternalFunctionItem"); do_externalitem (e); visit_collection ("generic_params", e.get_generic_params ()); std::string str = "none"; if (!e.get_function_params ().empty ()) for (auto ¶m : e.get_function_params ()) do_namefunctionparam (param); else put_field ("function_params", "none"); put_field ("has_variadics", std::to_string (e.is_variadic ())); visit_field ("return_type", e.get_return_type ()); end ("ExternalFunctionItem"); } void Dump::visit (ExternalTypeItem &e) { begin ("ExternalTypeItem"); do_externalitem (e); end ("ExternalTypeItem"); } void Dump::visit (ExternBlock &e) { begin ("ExternBlock"); do_vis_item (e); do_inner_attrs (e); put_field ("abi", get_string_from_abi (e.get_abi ())); visit_collection ("extern_items", e.get_extern_items ()); end ("ExternBlock"); } void Dump::visit (LiteralPattern &e) { begin ("LiteralPattern"); put_field ("lit", e.get_literal ().as_string ()); do_mappings (e.get_mappings ()); end ("LiteralPattern"); } void Dump::visit (IdentifierPattern &e) { begin ("IdentifierPattern"); put_field ("variable_ident", e.get_identifier ().as_string ()); put_field ("is_ref", std::to_string (e.get_is_ref ())); put_field ("mut", std::to_string (e.is_mut ())); if (e.has_pattern_to_bind ()) put_field ("to_bind", e.get_to_bind ()->as_string ()); else put_field ("to_bind", "none"); end ("IdentifierPattern"); } void Dump::visit (WildcardPattern &e) { begin ("WildcardPattern"); do_mappings (e.get_mappings ()); end ("WildcardPattern"); } void Dump::visit (RangePatternBoundLiteral &e) { begin ("RangePatternBoundLiteral"); put_field ("literal", e.get_literal ().as_string ()); put_field ("has_minus", std::to_string (e.get_has_minus ())); end ("RangePatternBoundLiteral"); } void Dump::visit (RangePatternBoundPath &e) { begin ("RangePatternBoundPath"); put_field ("path", e.get_path ().as_string ()); end ("RangePatternBoundPath"); } void Dump::visit (RangePatternBoundQualPath &e) { begin ("RangePatternBoundQualPath"); visit_field ("path", e.get_qualified_path ()); end ("RangePatternBoundQualPath"); } void Dump::visit (RangePattern &e) { begin ("RangePattern"); do_mappings (e.get_mappings ()); put_field ("lower", e.get_lower_bound ()->as_string ()); put_field ("upper", e.get_upper_bound ()->as_string ()); put_field ("has_ellipsis_syntax", std::to_string (e.get_has_ellipsis_syntax ())); end ("RangePattern"); } void Dump::visit (ReferencePattern &e) { begin ("ReferencePattern"); do_mappings (e.get_mappings ()); put_field ("mut", std::to_string (e.is_mut ())); put_field ("pattern", e.get_referenced_pattern ()->as_string ()); end ("ReferencePattern"); } void Dump::visit (StructPatternFieldTuplePat &e) { begin ("StructPatternFieldTuplePat"); do_mappings (e.get_mappings ()); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("index", std::to_string (e.get_index ())); put_field ("tuple_pattern", e.get_tuple_pattern ()->as_string ()); end ("StructPatternFieldTuplePat"); } void Dump::visit (StructPatternFieldIdentPat &e) { begin ("StructPatternFieldIdentPat"); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("ident", e.get_identifier ().as_string ()); put_field ("ident_pattern", e.get_pattern ()->as_string ()); end ("StructPatternFieldIdentPat"); } void Dump::visit (StructPatternFieldIdent &e) { begin ("StructPatternFieldIdent"); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("has_ref", std::to_string (e.get_has_ref ())); put_field ("mut", std::to_string (e.is_mut ())); put_field ("ident", e.get_identifier ().as_string ()); end ("StructPatternFieldIdent"); } void Dump::visit (StructPattern &e) { begin ("StructPattern"); visit_field ("path", e.get_path ()); put_field ("elems", e.get_struct_pattern_elems ().as_string ()); end ("StructPattern"); } void Dump::visit (TupleStructItemsNoRange &e) { begin ("TupleStructItemsNoRange"); visit_collection ("patterns", e.get_patterns ()); end ("TupleStructItemsNoRange"); } void Dump::visit (TupleStructItemsRange &e) { begin ("TupleStructItemsRange"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); end ("TupleStructItemsRange"); } void Dump::visit (TupleStructPattern &e) { begin ("TupleStructPattern"); do_mappings (e.get_mappings ()); put_field ("path", e.get_path ().as_string ()); visit_field ("items", e.get_items ()); end ("TupleStructPattern"); } void Dump::visit (TuplePatternItemsMultiple &e) { begin ("TuplePatternItemsMultiple"); visit_collection ("patterns", e.get_patterns ()); end ("TuplePatternItemsMultiple"); } void Dump::visit (TuplePatternItemsRanged &e) { begin ("TuplePatternItemsRanged"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); end ("TuplePatternItemsRanged"); } void Dump::visit (TuplePattern &e) { begin ("TuplePattern"); do_mappings (e.get_mappings ()); visit_field ("items", e.get_items ()); end ("TuplePattern"); } void Dump::visit (SlicePattern &e) { begin ("SlicePattern"); do_mappings (e.get_mappings ()); visit_collection ("items", e.get_items ()); end ("SlicePattern"); } void Dump::visit (AltPattern &e) { begin ("AltPattern"); do_mappings (e.get_mappings ()); visit_collection ("alts", e.get_alts ()); end ("AltPattern"); } void Dump::visit (EmptyStmt &e) { begin ("EmptyStmt"); do_stmt (e); end ("EmptyStmt"); } void Dump::visit (LetStmt &e) { begin ("LetStmt"); do_stmt (e); auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("variable_pattern", e.get_pattern ()->as_string ()); visit_field ("type", e.get_type ()); visit_field ("init_expr", e.get_init_expr ()); end ("LetStmt"); } void Dump::visit (ExprStmt &e) { begin ("ExprStmt"); do_stmt (e); put_field ("must_be_unit", std::to_string (e.is_unit_check_needed ())); visit_field ("expr", e.get_expr ()); end ("ExprStmt"); } void Dump::visit (TraitBound &e) { begin ("TraitBound"); do_mappings (e.get_mappings ()); put_field ("in_parens", std::to_string (e.get_in_parens ())); put_field ("polarity", BoundPolarityString (e.get_polarity ())); visit_collection ("for_lifetime", e.get_for_lifetimes ()); visit_field ("type_path", e.get_path ()); end ("TraitBound"); } void Dump::visit (ImplTraitType &e) { begin ("ImplTraitType"); do_type (e); visit_collection ("type_param_bounds", e.get_type_param_bounds ()); end ("ImplTraitType"); } void Dump::visit (TraitObjectType &e) { begin ("TraitObjectType"); do_type (e); put_field ("has_dyn", std::to_string (e.get_has_dyn ())); visit_collection ("type_param_bounds", e.get_type_param_bounds ()); end ("TraitObjectType"); } void Dump::visit (ParenthesisedType &e) { begin ("ParenthesisedType"); do_type (e); put_field ("type_in_parens", e.get_type_in_parens ()->as_string ()); end ("ParenthesisedType"); } void Dump::visit (ImplTraitTypeOneBound &e) { begin ("ImplTraitTypeOneBound"); do_type (e); visit_field ("trait_bound", e.get_trait_bound ()); end ("ImplTraitTypeOneBound"); } void Dump::visit (TupleType &e) { begin ("TupleType"); do_type (e); visit_collection ("elems", e.get_elems ()); end ("TupleType"); } void Dump::visit (NeverType &e) { begin ("NeverType"); do_type (e); end ("NeverType"); } void Dump::visit (RawPointerType &e) { begin ("RawPointerType"); do_type (e); put_field ("mut", Rust::enum_to_str (e.get_mut ())); put_field ("type", e.get_type ()->as_string ()); end ("RawPointerType"); } void Dump::visit (ReferenceType &e) { begin ("ReferenceType"); do_type (e); put_field ("lifetime", e.get_lifetime ().as_string ()); put_field ("mut", enum_to_str (e.get_mut ())); put_field ("type", e.get_base_type ()->as_string ()); end ("ReferenceType"); } void Dump::visit (ArrayType &e) { begin ("ArrayType"); do_type (e); visit_field ("type", e.get_element_type ()); visit_field ("size", e.get_size_expr ()); end ("ArrayType"); } void Dump::visit (SliceType &e) { begin ("SliceType"); do_type (e); visit_field ("elem_type", e.get_element_type ()); end ("SliceType"); } void Dump::visit (InferredType &e) { begin ("InferredType"); do_type (e); end ("InferredType"); } void Dump::visit (BareFunctionType &e) { begin ("BareFunctionType"); do_type (e); visit_collection ("for_lifetimes", e.get_for_lifetimes ()); put_field ("function_qualifiers", e.get_function_qualifiers ().as_string ()); if (e.get_function_params ().empty ()) { put_field ("params", "none"); } else { begin_field ("params"); for (auto ¶m : e.get_function_params ()) { begin ("MaybeNamedParam"); do_maybenamedparam (param); end ("MaybeNamedParam"); } end_field ("params"); } visit_field ("return_type", e.get_return_type ()); put_field ("is_variadic", std::to_string (e.get_is_variadic ())); end ("BareFunctionType"); } } // namespace HIR } // namespace Rust // In the global namespace to make it easier to call from debugger void debug (Rust::HIR::FullVisitable &v) { Rust::HIR::Dump::debug (v); }