(root)/
gcc-13.2.0/
gcc/
rust/
resolve/
rust-ast-resolve-toplevel.h
       1  // Copyright (C) 2020-2023 Free Software Foundation, Inc.
       2  
       3  // This file is part of GCC.
       4  
       5  // GCC is free software; you can redistribute it and/or modify it under
       6  // the terms of the GNU General Public License as published by the Free
       7  // Software Foundation; either version 3, or (at your option) any later
       8  // version.
       9  
      10  // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11  // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13  // for more details.
      14  
      15  // You should have received a copy of the GNU General Public License
      16  // along with GCC; see the file COPYING3.  If not see
      17  // <http://www.gnu.org/licenses/>.
      18  
      19  #ifndef RUST_AST_RESOLVE_TOPLEVEL_H
      20  #define RUST_AST_RESOLVE_TOPLEVEL_H
      21  
      22  #include "rust-ast-resolve-base.h"
      23  #include "rust-ast-resolve-type.h"
      24  #include "rust-ast-resolve-implitem.h"
      25  #include "rust-ast-full.h"
      26  #include "rust-name-resolver.h"
      27  #include "rust-session-manager.h"
      28  
      29  namespace Rust {
      30  namespace Resolver {
      31  
      32  class ResolveTopLevel : public ResolverBase
      33  {
      34    using Rust::Resolver::ResolverBase::visit;
      35  
      36  public:
      37    static void go (AST::Item *item, const CanonicalPath &prefix,
      38  		  const CanonicalPath &canonical_prefix)
      39    {
      40      if (item->is_marked_for_strip ())
      41        return;
      42  
      43      ResolveTopLevel resolver (prefix, canonical_prefix);
      44      item->accept_vis (resolver);
      45  
      46      NodeId current_module = resolver.resolver->peek_current_module_scope ();
      47      resolver.mappings->insert_child_item_to_parent_module_mapping (
      48        item->get_node_id (), current_module);
      49    }
      50  
      51    void visit (AST::Module &module) override
      52    {
      53      auto mod
      54        = CanonicalPath::new_seg (module.get_node_id (), module.get_name ());
      55      auto path = prefix.append (mod);
      56      auto cpath = canonical_prefix.append (mod);
      57  
      58      resolver->get_name_scope ().insert (
      59        path, module.get_node_id (), module.get_locus (), false,
      60        Rib::ItemType::Module,
      61        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
      62  	RichLocation r (module.get_locus ());
      63  	r.add_range (locus);
      64  	rust_error_at (r, "redefined multiple times");
      65        });
      66  
      67      NodeId current_module = resolver->peek_current_module_scope ();
      68      mappings->insert_module_child_item (current_module, mod);
      69      mappings->insert_module_child (current_module, module.get_node_id ());
      70  
      71      resolver->push_new_module_scope (module.get_node_id ());
      72      for (auto &item : module.get_items ())
      73        ResolveTopLevel::go (item.get (), path, cpath);
      74  
      75      resolver->pop_module_scope ();
      76  
      77      mappings->insert_canonical_path (module.get_node_id (), cpath);
      78    }
      79  
      80    void visit (AST::TypeAlias &alias) override
      81    {
      82      auto talias = CanonicalPath::new_seg (alias.get_node_id (),
      83  					  alias.get_new_type_name ());
      84      auto path = prefix.append (talias);
      85      auto cpath = canonical_prefix.append (talias);
      86  
      87      resolver->get_type_scope ().insert (
      88        path, alias.get_node_id (), alias.get_locus (), false,
      89        Rib::ItemType::Type,
      90        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
      91  	RichLocation r (alias.get_locus ());
      92  	r.add_range (locus);
      93  	rust_error_at (r, "redefined multiple times");
      94        });
      95  
      96      NodeId current_module = resolver->peek_current_module_scope ();
      97      mappings->insert_module_child_item (current_module, talias);
      98      mappings->insert_canonical_path (alias.get_node_id (), cpath);
      99    }
     100  
     101    void visit (AST::TupleStruct &struct_decl) override
     102    {
     103      auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
     104  					struct_decl.get_identifier ());
     105      auto path = prefix.append (decl);
     106      auto cpath = canonical_prefix.append (decl);
     107  
     108      resolver->get_type_scope ().insert (
     109        path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
     110        Rib::ItemType::Type,
     111        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     112  	RichLocation r (struct_decl.get_locus ());
     113  	r.add_range (locus);
     114  	rust_error_at (r, "redefined multiple times");
     115        });
     116  
     117      NodeId current_module = resolver->peek_current_module_scope ();
     118      mappings->insert_module_child_item (current_module, decl);
     119      mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
     120    }
     121  
     122    void visit (AST::Enum &enum_decl) override
     123    {
     124      auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
     125  					enum_decl.get_identifier ());
     126      auto path = prefix.append (decl);
     127      auto cpath = canonical_prefix.append (decl);
     128  
     129      resolver->get_type_scope ().insert (
     130        path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
     131        Rib::ItemType::Type,
     132        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     133  	RichLocation r (enum_decl.get_locus ());
     134  	r.add_range (locus);
     135  	rust_error_at (r, "redefined multiple times");
     136        });
     137  
     138      for (auto &variant : enum_decl.get_variants ())
     139        ResolveTopLevel::go (variant.get (), path, cpath);
     140  
     141      NodeId current_module = resolver->peek_current_module_scope ();
     142      mappings->insert_module_child_item (current_module, decl);
     143      mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
     144    }
     145  
     146    void visit (AST::EnumItem &item) override
     147    {
     148      auto decl
     149        = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
     150      auto path = prefix.append (decl);
     151      auto cpath = canonical_prefix.append (decl);
     152  
     153      resolver->get_type_scope ().insert (
     154        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     155        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     156  	RichLocation r (item.get_locus ());
     157  	r.add_range (locus);
     158  	rust_error_at (r, "redefined multiple times");
     159        });
     160  
     161      mappings->insert_canonical_path (item.get_node_id (), cpath);
     162    }
     163  
     164    void visit (AST::EnumItemTuple &item) override
     165    {
     166      auto decl
     167        = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
     168      auto path = prefix.append (decl);
     169      auto cpath = canonical_prefix.append (decl);
     170  
     171      resolver->get_type_scope ().insert (
     172        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     173        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     174  	RichLocation r (item.get_locus ());
     175  	r.add_range (locus);
     176  	rust_error_at (r, "redefined multiple times");
     177        });
     178  
     179      mappings->insert_canonical_path (item.get_node_id (), cpath);
     180    }
     181  
     182    void visit (AST::EnumItemStruct &item) override
     183    {
     184      auto decl
     185        = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
     186      auto path = prefix.append (decl);
     187      auto cpath = canonical_prefix.append (decl);
     188  
     189      resolver->get_type_scope ().insert (
     190        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     191        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     192  	RichLocation r (item.get_locus ());
     193  	r.add_range (locus);
     194  	rust_error_at (r, "redefined multiple times");
     195        });
     196  
     197      mappings->insert_canonical_path (item.get_node_id (), cpath);
     198    }
     199  
     200    void visit (AST::EnumItemDiscriminant &item) override
     201    {
     202      auto decl
     203        = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
     204      auto path = prefix.append (decl);
     205      auto cpath = canonical_prefix.append (decl);
     206  
     207      resolver->get_type_scope ().insert (
     208        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     209        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     210  	RichLocation r (item.get_locus ());
     211  	r.add_range (locus);
     212  	rust_error_at (r, "redefined multiple times");
     213        });
     214  
     215      mappings->insert_canonical_path (item.get_node_id (), cpath);
     216    }
     217  
     218    void visit (AST::StructStruct &struct_decl) override
     219    {
     220      auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
     221  					struct_decl.get_identifier ());
     222      auto path = prefix.append (decl);
     223      auto cpath = canonical_prefix.append (decl);
     224  
     225      resolver->get_type_scope ().insert (
     226        path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
     227        Rib::ItemType::Type,
     228        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     229  	RichLocation r (struct_decl.get_locus ());
     230  	r.add_range (locus);
     231  	rust_error_at (r, "redefined multiple times");
     232        });
     233  
     234      NodeId current_module = resolver->peek_current_module_scope ();
     235      mappings->insert_module_child_item (current_module, decl);
     236      mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
     237    }
     238  
     239    void visit (AST::Union &union_decl) override
     240    {
     241      auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
     242  					union_decl.get_identifier ());
     243      auto path = prefix.append (decl);
     244      auto cpath = canonical_prefix.append (decl);
     245  
     246      resolver->get_type_scope ().insert (
     247        path, union_decl.get_node_id (), union_decl.get_locus (), false,
     248        Rib::ItemType::Type,
     249        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     250  	RichLocation r (union_decl.get_locus ());
     251  	r.add_range (locus);
     252  	rust_error_at (r, "redefined multiple times");
     253        });
     254  
     255      NodeId current_module = resolver->peek_current_module_scope ();
     256      mappings->insert_module_child_item (current_module, decl);
     257      mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
     258    }
     259  
     260    void visit (AST::StaticItem &var) override
     261    {
     262      auto decl
     263        = CanonicalPath::new_seg (var.get_node_id (), var.get_identifier ());
     264      auto path = prefix.append (decl);
     265      auto cpath = canonical_prefix.append (decl);
     266  
     267      resolver->get_name_scope ().insert (
     268        path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static,
     269        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     270  	RichLocation r (var.get_locus ());
     271  	r.add_range (locus);
     272  	rust_error_at (r, "redefined multiple times");
     273        });
     274  
     275      NodeId current_module = resolver->peek_current_module_scope ();
     276      mappings->insert_module_child_item (current_module, decl);
     277      mappings->insert_canonical_path (var.get_node_id (), cpath);
     278    }
     279  
     280    void visit (AST::ConstantItem &constant) override
     281    {
     282      auto decl = CanonicalPath::new_seg (constant.get_node_id (),
     283  					constant.get_identifier ());
     284      auto path = prefix.append (decl);
     285      auto cpath = canonical_prefix.append (decl);
     286  
     287      resolver->get_name_scope ().insert (
     288        path, constant.get_node_id (), constant.get_locus (), false,
     289        Rib::ItemType::Const,
     290        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     291  	RichLocation r (constant.get_locus ());
     292  	r.add_range (locus);
     293  	rust_error_at (r, "redefined multiple times");
     294        });
     295  
     296      NodeId current_module = resolver->peek_current_module_scope ();
     297      mappings->insert_module_child_item (current_module, decl);
     298      mappings->insert_canonical_path (constant.get_node_id (), cpath);
     299    }
     300  
     301    void visit (AST::Function &function) override
     302    {
     303      auto decl = CanonicalPath::new_seg (function.get_node_id (),
     304  					function.get_function_name ());
     305      auto path = prefix.append (decl);
     306      auto cpath = canonical_prefix.append (decl);
     307  
     308      resolver->get_name_scope ().insert (
     309        path, function.get_node_id (), function.get_locus (), false,
     310        Rib::ItemType::Function,
     311        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     312  	RichLocation r (function.get_locus ());
     313  	r.add_range (locus);
     314  	rust_error_at (r, "redefined multiple times");
     315        });
     316  
     317      NodeId current_module = resolver->peek_current_module_scope ();
     318      mappings->insert_module_child_item (current_module, decl);
     319      mappings->insert_canonical_path (function.get_node_id (), cpath);
     320    }
     321  
     322    void visit (AST::InherentImpl &impl_block) override
     323    {
     324      std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
     325      CanonicalPath impl_type
     326        = CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
     327  				raw_impl_type_path);
     328      CanonicalPath impl_prefix = prefix.append (impl_type);
     329  
     330      for (auto &impl_item : impl_block.get_impl_items ())
     331        ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
     332    }
     333  
     334    void visit (AST::TraitImpl &impl_block) override
     335    {
     336      std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
     337      CanonicalPath impl_type_seg
     338        = CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
     339  				raw_impl_type_path);
     340  
     341      std::string raw_trait_type_path = impl_block.get_trait_path ().as_string ();
     342      CanonicalPath trait_type_seg
     343        = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (),
     344  				raw_trait_type_path);
     345  
     346      CanonicalPath projection
     347        = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
     348  						  trait_type_seg,
     349  						  impl_type_seg);
     350      CanonicalPath impl_prefix = prefix.append (projection);
     351  
     352      resolver->get_name_scope ().insert (
     353        impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
     354        Rib::ItemType::TraitImpl,
     355        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     356  	RichLocation r (impl_block.get_locus ());
     357  	r.add_range (locus);
     358  	rust_error_at (r, "redefined multiple times");
     359        });
     360  
     361      for (auto &impl_item : impl_block.get_impl_items ())
     362        ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
     363    }
     364  
     365    void visit (AST::Trait &trait) override
     366    {
     367      auto decl
     368        = CanonicalPath::new_seg (trait.get_node_id (), trait.get_identifier ());
     369      auto path = prefix.append (decl);
     370      auto cpath = canonical_prefix.append (decl);
     371  
     372      resolver->get_type_scope ().insert (
     373        path, trait.get_node_id (), trait.get_locus (), false,
     374        Rib::ItemType::Trait,
     375        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     376  	RichLocation r (trait.get_locus ());
     377  	r.add_range (locus);
     378  	rust_error_at (r, "redefined multiple times");
     379        });
     380  
     381      for (auto &item : trait.get_trait_items ())
     382        ResolveTopLevelTraitItems::go (item.get (), path, cpath);
     383  
     384      NodeId current_module = resolver->peek_current_module_scope ();
     385      mappings->insert_module_child_item (current_module, decl);
     386      mappings->insert_canonical_path (trait.get_node_id (), cpath);
     387    }
     388  
     389    void visit (AST::ExternBlock &extern_block) override
     390    {
     391      for (auto &item : extern_block.get_extern_items ())
     392        {
     393  	ResolveToplevelExternItem::go (item.get (), prefix);
     394        }
     395    }
     396  
     397    void visit (AST::ExternCrate &extern_crate) override
     398    {
     399      if (extern_crate.is_marked_for_strip ())
     400        return;
     401  
     402      NodeId resolved_crate = UNKNOWN_NODEID;
     403      if (extern_crate.references_self ())
     404        {
     405  	CrateNum crate_num = mappings->get_current_crate ();
     406  	bool ok = mappings->crate_num_to_nodeid (crate_num, resolved_crate);
     407  	rust_assert (ok);
     408        }
     409      else
     410        {
     411  	CrateNum found_crate_num = UNKNOWN_CREATENUM;
     412  	bool found
     413  	  = mappings->lookup_crate_name (extern_crate.get_referenced_crate (),
     414  					 found_crate_num);
     415  	if (!found)
     416  	  {
     417  	    rust_error_at (extern_crate.get_locus (), "unknown crate %<%s%>",
     418  			   extern_crate.get_referenced_crate ().c_str ());
     419  	    return;
     420  	  }
     421  
     422  	bool ok
     423  	  = mappings->crate_num_to_nodeid (found_crate_num, resolved_crate);
     424  	if (!ok)
     425  	  {
     426  	    rust_internal_error_at (extern_crate.get_locus (),
     427  				    "failed to resolve crate to nodeid");
     428  	    return;
     429  	  }
     430        }
     431  
     432      if (resolved_crate == UNKNOWN_NODEID)
     433        {
     434  	rust_error_at (extern_crate.get_locus (), "failed to resolve crate");
     435  	return;
     436        }
     437  
     438      // mark the node as resolved
     439      resolver->insert_resolved_name (extern_crate.get_node_id (),
     440  				    resolved_crate);
     441      CanonicalPath decl
     442        = extern_crate.has_as_clause ()
     443  	  ? CanonicalPath::new_seg (extern_crate.get_node_id (),
     444  				    extern_crate.get_as_clause ())
     445  	  : CanonicalPath::new_seg (extern_crate.get_node_id (),
     446  				    extern_crate.get_referenced_crate ());
     447  
     448      resolver->get_type_scope ().insert (
     449        decl, resolved_crate, extern_crate.get_locus (), false,
     450        Rib::ItemType::ExternCrate,
     451        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     452  	RichLocation r (extern_crate.get_locus ());
     453  	r.add_range (locus);
     454  	rust_error_at (r, "redefined multiple times");
     455        });
     456    }
     457  
     458  private:
     459    ResolveTopLevel (const CanonicalPath &prefix,
     460  		   const CanonicalPath &canonical_prefix)
     461      : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
     462    {}
     463  
     464    const CanonicalPath &prefix;
     465    const CanonicalPath &canonical_prefix;
     466  };
     467  
     468  } // namespace Resolver
     469  } // namespace Rust
     470  
     471  #endif // RUST_AST_RESOLVE_TOPLEVEL_H