| // 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 |
| // <http://www.gnu.org/licenses/>. |
| |
| #ifndef RUST_NAME_RESOLVER_H |
| #define RUST_NAME_RESOLVER_H |
| |
| #include "rust-system.h" |
| #include "rust-canonical-path.h" |
| #include "rust-hir-map.h" |
| #include "rust-hir-type-check.h" |
| |
| namespace Rust { |
| namespace Resolver { |
| |
| class Rib |
| { |
| public: |
| enum ItemType |
| { |
| Var, |
| Param, |
| Function, |
| Type, |
| Module, |
| Static, |
| Const, |
| Trait, |
| Impl, |
| TraitImpl, |
| ExternCrate, |
| MacroDecl, |
| Label, |
| Unknown |
| }; |
| |
| // FIXME |
| // Rust uses local_def_ids assigned by def_collector on the AST. Consider |
| // moving to a local-def-id |
| Rib (CrateNum crateNum, NodeId node_id); |
| |
| // this takes the relative paths of items within a compilation unit for lookup |
| void insert_name ( |
| const CanonicalPath &path, NodeId id, location_t locus, bool shadow, |
| ItemType type, |
| std::function<void (const CanonicalPath &, NodeId, location_t)> dup_cb); |
| |
| bool lookup_canonical_path (const NodeId &id, CanonicalPath *ident); |
| bool lookup_name (const CanonicalPath &ident, NodeId *id); |
| void clear_name (const CanonicalPath &ident, NodeId id); |
| void append_reference_for_def (NodeId def, NodeId ref); |
| bool have_references_for_node (NodeId def) const; |
| bool decl_was_declared_here (NodeId def) const; |
| bool lookup_decl_type (NodeId def, ItemType *type) const; |
| void debug () const; |
| std::string debug_str () const; |
| |
| CrateNum get_crate_num () const { return crate_num; } |
| NodeId get_node_id () const { return node_id; } |
| std::map<NodeId, location_t> &get_declarations () { return decls_within_rib; } |
| |
| private: |
| CrateNum crate_num; |
| NodeId node_id; |
| std::map<CanonicalPath, NodeId> path_mappings; |
| std::map<NodeId, CanonicalPath> reverse_path_mappings; |
| std::map<NodeId, location_t> decls_within_rib; |
| std::map<NodeId, std::set<NodeId>> references; |
| std::map<NodeId, ItemType> decl_type_mappings; |
| }; |
| |
| class Scope |
| { |
| public: |
| Scope (CrateNum crate_num); |
| |
| void insert ( |
| const CanonicalPath &ident, NodeId id, location_t locus, bool shadow, |
| Rib::ItemType type, |
| std::function<void (const CanonicalPath &, NodeId, location_t)> dup_cb); |
| |
| void insert (const CanonicalPath &ident, NodeId id, location_t locus, |
| Rib::ItemType type = Rib::ItemType::Unknown); |
| bool lookup (const CanonicalPath &ident, NodeId *id); |
| bool lookup_decl_type (NodeId id, Rib::ItemType *type); |
| bool lookup_rib_for_decl (NodeId id, const Rib **rib); |
| |
| void iterate (std::function<bool (Rib *)> cb); |
| void iterate (std::function<bool (const Rib *)> cb) const; |
| |
| Rib *peek (); |
| void push (NodeId id); |
| Rib *pop (); |
| |
| bool decl_was_declared_here (NodeId def) const; |
| void append_reference_for_def (NodeId refId, NodeId defId); |
| |
| CrateNum get_crate_num () const { return crate_num; } |
| |
| const std::vector<Rib *> &get_context () const { return stack; }; |
| |
| private: |
| CrateNum crate_num; |
| std::vector<Rib *> stack; |
| }; |
| |
| class Resolver |
| { |
| public: |
| static Resolver *get (); |
| ~Resolver () {} |
| |
| // these builtin types |
| void insert_builtin_types (Rib *r); |
| |
| // these will be required for type resolution passes to |
| // map back to tyty nodes |
| std::vector<AST::Type *> &get_builtin_types (); |
| |
| void push_new_name_rib (Rib *r); |
| void push_new_type_rib (Rib *r); |
| void push_new_label_rib (Rib *r); |
| void push_new_macro_rib (Rib *r); |
| |
| bool find_name_rib (NodeId id, Rib **rib); |
| bool find_type_rib (NodeId id, Rib **rib); |
| bool find_label_rib (NodeId id, Rib **rib); |
| bool find_macro_rib (NodeId id, Rib **rib); |
| |
| void insert_resolved_name (NodeId refId, NodeId defId); |
| bool lookup_resolved_name (NodeId refId, NodeId *defId); |
| |
| void insert_resolved_type (NodeId refId, NodeId defId); |
| bool lookup_resolved_type (NodeId refId, NodeId *defId); |
| |
| void insert_resolved_label (NodeId refId, NodeId defId); |
| bool lookup_resolved_label (NodeId refId, NodeId *defId); |
| |
| void insert_resolved_macro (NodeId refId, NodeId defId); |
| bool lookup_resolved_macro (NodeId refId, NodeId *defId); |
| |
| void insert_resolved_misc (NodeId refId, NodeId defId); |
| bool lookup_resolved_misc (NodeId refId, NodeId *defId); |
| |
| // proxy for scoping |
| Scope &get_name_scope () { return name_scope; } |
| Scope &get_type_scope () { return type_scope; } |
| Scope &get_label_scope () { return label_scope; } |
| Scope &get_macro_scope () { return macro_scope; } |
| |
| NodeId get_global_type_node_id () { return global_type_node_id; } |
| |
| void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } |
| NodeId get_unit_type_node_id () { return unit_ty_node_id; } |
| |
| void set_never_type_node_id (NodeId id) { never_ty_node_id = id; } |
| NodeId get_never_type_node_id () { return never_ty_node_id; } |
| |
| void push_new_module_scope (NodeId module_id) |
| { |
| current_module_stack.push_back (module_id); |
| } |
| |
| void pop_module_scope () |
| { |
| rust_assert (!current_module_stack.empty ()); |
| current_module_stack.pop_back (); |
| } |
| |
| NodeId peek_current_module_scope () const |
| { |
| rust_assert (!current_module_stack.empty ()); |
| return current_module_stack.back (); |
| } |
| |
| NodeId peek_crate_module_scope () const |
| { |
| rust_assert (!current_module_stack.empty ()); |
| return current_module_stack.front (); |
| } |
| |
| NodeId peek_parent_module_scope () const |
| { |
| rust_assert (current_module_stack.size () > 1); |
| return current_module_stack.at (current_module_stack.size () - 2); |
| } |
| |
| void push_closure_context (NodeId closure_expr_id); |
| void pop_closure_context (); |
| void insert_captured_item (NodeId id); |
| const std::set<NodeId> &get_captures (NodeId id) const; |
| |
| std::string as_debug_string () const |
| { |
| std::stringstream ss; |
| |
| ss << "Names:\n"; |
| for (auto &n : name_ribs) |
| { |
| ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () |
| << "\n"; |
| } |
| ss << "Types:\n"; |
| for (auto &n : type_ribs) |
| { |
| ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () |
| << "\n"; |
| } |
| ss << "Macros:\n"; |
| |
| for (auto &n : macro_ribs) |
| { |
| ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () |
| << "\n"; |
| } |
| |
| ss << "Labels:\n"; |
| |
| for (auto &n : label_ribs) |
| { |
| ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () |
| << "\n"; |
| } |
| |
| return ss.str (); |
| } |
| |
| protected: |
| bool decl_needs_capture (NodeId decl_rib_node_id, NodeId closure_rib_node_id, |
| const Scope &scope); |
| |
| private: |
| Resolver (); |
| |
| void generate_builtins (); |
| NodeId setup_builtin (const std::string &name, TyTy::BaseType *tyty); |
| |
| Analysis::Mappings &mappings; |
| TypeCheckContext *tyctx; |
| |
| std::vector<AST::Type *> builtins; |
| |
| Scope name_scope; |
| Scope type_scope; |
| Scope label_scope; |
| Scope macro_scope; |
| |
| NodeId global_type_node_id; |
| NodeId unit_ty_node_id; |
| NodeId never_ty_node_id; |
| |
| // map a AST Node to a Rib |
| std::map<NodeId, Rib *> name_ribs; |
| std::map<NodeId, Rib *> type_ribs; |
| std::map<NodeId, Rib *> label_ribs; |
| std::map<NodeId, Rib *> macro_ribs; |
| |
| // Rust uses DefIds to namespace these under a crate_num |
| // but then it uses the def_collector to assign local_defids |
| // to each ast node as well. not sure if this is going to fit |
| // with gcc very well to compile a full crate in one go but we will |
| // see. |
| |
| // these are of the form ref->Def-NodeId |
| // we need two namespaces one for names and ones for types |
| std::map<NodeId, NodeId> resolved_names; |
| std::map<NodeId, NodeId> resolved_types; |
| std::map<NodeId, NodeId> resolved_labels; |
| std::map<NodeId, NodeId> resolved_macros; |
| |
| // misc |
| std::map<NodeId, NodeId> misc_resolved_items; |
| |
| // keep track of the current module scope ids |
| std::vector<NodeId> current_module_stack; |
| |
| // captured variables mappings |
| std::vector<NodeId> closure_context; |
| std::map<NodeId, std::set<NodeId>> closures_capture_mappings; |
| }; |
| |
| } // namespace Resolver |
| } // namespace Rust |
| |
| #endif // RUST_NAME_RESOLVER_H |