(root)/
gcc-13.2.0/
gcc/
rust/
resolve/
rust-ast-resolve-stmt.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_STMT_H
      20  #define RUST_AST_RESOLVE_STMT_H
      21  
      22  #include "rust-ast-resolve-base.h"
      23  #include "rust-ast-full.h"
      24  #include "rust-ast-resolve-type.h"
      25  #include "rust-ast-resolve-pattern.h"
      26  #include "rust-ast-resolve-expr.h"
      27  
      28  namespace Rust {
      29  namespace Resolver {
      30  
      31  class ResolveStmt : public ResolverBase
      32  {
      33    using Rust::Resolver::ResolverBase::visit;
      34  
      35  public:
      36    static void go (AST::Stmt *stmt, const CanonicalPath &prefix,
      37  		  const CanonicalPath &canonical_prefix,
      38  		  const CanonicalPath &enum_prefix)
      39    {
      40      if (stmt->is_marked_for_strip ())
      41        return;
      42  
      43      ResolveStmt resolver (prefix, canonical_prefix, enum_prefix);
      44      stmt->accept_vis (resolver);
      45    }
      46  
      47    void visit (AST::ExprStmtWithBlock &stmt) override
      48    {
      49      ResolveExpr::go (stmt.get_expr ().get (), prefix, canonical_prefix);
      50    }
      51  
      52    void visit (AST::ExprStmtWithoutBlock &stmt) override
      53    {
      54      ResolveExpr::go (stmt.get_expr ().get (), prefix, canonical_prefix);
      55    }
      56  
      57    void visit (AST::ConstantItem &constant) override
      58    {
      59      auto decl = CanonicalPath::new_seg (constant.get_node_id (),
      60  					constant.get_identifier ());
      61      auto path = decl; // this ensures we have the correct relative resolution
      62      auto cpath = canonical_prefix.append (decl);
      63      mappings->insert_canonical_path (constant.get_node_id (), cpath);
      64  
      65      resolver->get_name_scope ().insert (
      66        path, constant.get_node_id (), constant.get_locus (), false,
      67        Rib::ItemType::Const,
      68        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
      69  	RichLocation r (constant.get_locus ());
      70  	r.add_range (locus);
      71  	rust_error_at (r, "redefined multiple times");
      72        });
      73  
      74      ResolveType::go (constant.get_type ().get ());
      75      ResolveExpr::go (constant.get_expr ().get (), prefix, canonical_prefix);
      76    }
      77  
      78    void visit (AST::LetStmt &stmt) override
      79    {
      80      if (stmt.has_init_expr ())
      81        {
      82  	ResolveExpr::go (stmt.get_init_expr ().get (), prefix,
      83  			 canonical_prefix);
      84        }
      85  
      86      PatternDeclaration::go (stmt.get_pattern ().get (), Rib::ItemType::Var);
      87      if (stmt.has_type ())
      88        ResolveType::go (stmt.get_type ().get ());
      89    }
      90  
      91    void visit (AST::TupleStruct &struct_decl) override
      92    {
      93      auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
      94  					struct_decl.get_identifier ());
      95      auto path = decl; // this ensures we have the correct relative resolution
      96      auto cpath = canonical_prefix.append (decl);
      97      mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
      98  
      99      resolver->get_type_scope ().insert (
     100        path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
     101        Rib::ItemType::Type,
     102        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     103  	RichLocation r (struct_decl.get_locus ());
     104  	r.add_range (locus);
     105  	rust_error_at (r, "redefined multiple times");
     106        });
     107  
     108      NodeId scope_node_id = struct_decl.get_node_id ();
     109      resolver->get_type_scope ().push (scope_node_id);
     110  
     111      if (struct_decl.has_generics ())
     112        {
     113  	for (auto &generic : struct_decl.get_generic_params ())
     114  	  ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
     115        }
     116  
     117      for (AST::TupleField &field : struct_decl.get_fields ())
     118        ResolveType::go (field.get_field_type ().get ());
     119  
     120      resolver->get_type_scope ().pop ();
     121    }
     122  
     123    void visit (AST::Enum &enum_decl) override
     124    {
     125      auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
     126  					enum_decl.get_identifier ());
     127      auto path = decl; // this ensures we have the correct relative resolution
     128      auto cpath = canonical_prefix.append (decl);
     129      mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
     130  
     131      resolver->get_type_scope ().insert (
     132        path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
     133        Rib::ItemType::Type,
     134        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     135  	RichLocation r (enum_decl.get_locus ());
     136  	r.add_range (locus);
     137  	rust_error_at (r, "redefined multiple times");
     138        });
     139  
     140      NodeId scope_node_id = enum_decl.get_node_id ();
     141      resolver->get_type_scope ().push (scope_node_id);
     142  
     143      if (enum_decl.has_generics ())
     144        {
     145  	for (auto &generic : enum_decl.get_generic_params ())
     146  	  ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
     147        }
     148  
     149      for (auto &variant : enum_decl.get_variants ())
     150        ResolveStmt::go (variant.get (), path, canonical_prefix, path);
     151  
     152      resolver->get_type_scope ().pop ();
     153    }
     154  
     155    void visit (AST::EnumItem &item) override
     156    {
     157      auto decl = enum_prefix.append (
     158        CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
     159      auto path = decl; // this ensures we have the correct relative resolution
     160      auto cpath = canonical_prefix.append (decl);
     161      mappings->insert_canonical_path (item.get_node_id (), cpath);
     162  
     163      resolver->get_type_scope ().insert (
     164        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     165        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     166  	RichLocation r (item.get_locus ());
     167  	r.add_range (locus);
     168  	rust_error_at (r, "redefined multiple times");
     169        });
     170  
     171      // Done, no fields.
     172    }
     173  
     174    void visit (AST::EnumItemTuple &item) override
     175    {
     176      auto decl = enum_prefix.append (
     177        CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
     178      auto path = decl; // this ensures we have the correct relative resolution
     179      auto cpath = canonical_prefix.append (decl);
     180      mappings->insert_canonical_path (item.get_node_id (), cpath);
     181  
     182      resolver->get_type_scope ().insert (
     183        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     184        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     185  	RichLocation r (item.get_locus ());
     186  	r.add_range (locus);
     187  	rust_error_at (r, "redefined multiple times");
     188        });
     189  
     190      for (auto &field : item.get_tuple_fields ())
     191        {
     192  	if (field.get_field_type ()->is_marked_for_strip ())
     193  	  continue;
     194  
     195  	ResolveType::go (field.get_field_type ().get ());
     196        }
     197    }
     198  
     199    void visit (AST::EnumItemStruct &item) override
     200    {
     201      auto decl = enum_prefix.append (
     202        CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
     203      auto path = decl; // this ensures we have the correct relative resolution
     204      auto cpath = canonical_prefix.append (decl);
     205      mappings->insert_canonical_path (item.get_node_id (), cpath);
     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      for (auto &field : item.get_struct_fields ())
     216        {
     217  	if (field.get_field_type ()->is_marked_for_strip ())
     218  	  continue;
     219  
     220  	ResolveType::go (field.get_field_type ().get ());
     221        }
     222    }
     223  
     224    void visit (AST::EnumItemDiscriminant &item) override
     225    {
     226      auto decl = enum_prefix.append (
     227        CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
     228      auto path = decl; // this ensures we have the correct relative resolution
     229      auto cpath = canonical_prefix.append (decl);
     230      mappings->insert_canonical_path (item.get_node_id (), cpath);
     231  
     232      resolver->get_type_scope ().insert (
     233        path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
     234        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     235  	RichLocation r (item.get_locus ());
     236  	r.add_range (locus);
     237  	rust_error_at (r, "redefined multiple times");
     238        });
     239  
     240      // Done, no fields.
     241    }
     242  
     243    void visit (AST::StructStruct &struct_decl) override
     244    {
     245      auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
     246  					struct_decl.get_identifier ());
     247      auto path = decl; // this ensures we have the correct relative resolution
     248      auto cpath = canonical_prefix.append (decl);
     249      mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
     250  
     251      resolver->get_type_scope ().insert (
     252        path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
     253        Rib::ItemType::Type,
     254        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     255  	RichLocation r (struct_decl.get_locus ());
     256  	r.add_range (locus);
     257  	rust_error_at (r, "redefined multiple times");
     258        });
     259  
     260      NodeId scope_node_id = struct_decl.get_node_id ();
     261      resolver->get_type_scope ().push (scope_node_id);
     262  
     263      if (struct_decl.has_generics ())
     264        {
     265  	for (auto &generic : struct_decl.get_generic_params ())
     266  	  ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
     267        }
     268  
     269      for (AST::StructField &field : struct_decl.get_fields ())
     270        {
     271  	if (field.get_field_type ()->is_marked_for_strip ())
     272  	  continue;
     273  
     274  	ResolveType::go (field.get_field_type ().get ());
     275        }
     276  
     277      resolver->get_type_scope ().pop ();
     278    }
     279  
     280    void visit (AST::Union &union_decl) override
     281    {
     282      auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
     283  					union_decl.get_identifier ());
     284      auto path = decl; // this ensures we have the correct relative resolution
     285      auto cpath = canonical_prefix.append (decl);
     286      mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
     287  
     288      resolver->get_type_scope ().insert (
     289        path, union_decl.get_node_id (), union_decl.get_locus (), false,
     290        Rib::ItemType::Type,
     291        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     292  	RichLocation r (union_decl.get_locus ());
     293  	r.add_range (locus);
     294  	rust_error_at (r, "redefined multiple times");
     295        });
     296  
     297      NodeId scope_node_id = union_decl.get_node_id ();
     298      resolver->get_type_scope ().push (scope_node_id);
     299  
     300      if (union_decl.has_generics ())
     301        for (auto &generic : union_decl.get_generic_params ())
     302  	ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
     303  
     304      for (AST::StructField &field : union_decl.get_variants ())
     305        {
     306  	if (field.get_field_type ()->is_marked_for_strip ())
     307  	  continue;
     308  
     309  	ResolveType::go (field.get_field_type ().get ());
     310        }
     311  
     312      resolver->get_type_scope ().pop ();
     313    }
     314  
     315    void visit (AST::Function &function) override
     316    {
     317      auto decl = CanonicalPath::new_seg (function.get_node_id (),
     318  					function.get_function_name ());
     319      auto path = decl; // this ensures we have the correct relative resolution
     320      auto cpath = canonical_prefix.append (decl);
     321      mappings->insert_canonical_path (function.get_node_id (), cpath);
     322  
     323      resolver->get_name_scope ().insert (
     324        path, function.get_node_id (), function.get_locus (), false,
     325        Rib::ItemType::Function,
     326        [&] (const CanonicalPath &, NodeId, Location locus) -> void {
     327  	RichLocation r (function.get_locus ());
     328  	r.add_range (locus);
     329  	rust_error_at (r, "redefined multiple times");
     330        });
     331  
     332      NodeId scope_node_id = function.get_node_id ();
     333      resolver->get_name_scope ().push (scope_node_id);
     334      resolver->get_type_scope ().push (scope_node_id);
     335      resolver->get_label_scope ().push (scope_node_id);
     336      resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
     337      resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
     338      resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
     339  
     340      if (function.has_generics ())
     341        for (auto &generic : function.get_generic_params ())
     342  	ResolveGenericParam::go (generic.get (), prefix, canonical_prefix);
     343  
     344      if (function.has_return_type ())
     345        ResolveType::go (function.get_return_type ().get ());
     346  
     347      // we make a new scope so the names of parameters are resolved and shadowed
     348      // correctly
     349      for (auto &param : function.get_function_params ())
     350        {
     351  	ResolveType::go (param.get_type ().get ());
     352  	PatternDeclaration::go (param.get_pattern ().get (),
     353  				Rib::ItemType::Param);
     354        }
     355  
     356      // resolve the function body
     357      ResolveExpr::go (function.get_definition ().get (), path, cpath);
     358  
     359      resolver->get_name_scope ().pop ();
     360      resolver->get_type_scope ().pop ();
     361      resolver->get_label_scope ().pop ();
     362    }
     363  
     364    void visit (AST::ExternBlock &extern_block) override;
     365  
     366  private:
     367    ResolveStmt (const CanonicalPath &prefix,
     368  	       const CanonicalPath &canonical_prefix,
     369  	       const CanonicalPath &enum_prefix)
     370      : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
     371        enum_prefix (enum_prefix)
     372    {}
     373  
     374    const CanonicalPath &prefix;
     375    const CanonicalPath &canonical_prefix;
     376  
     377    /* item declaration statements are not given a canonical path, but enum items
     378     * (variants) do inherit the enum path/identifier name.  */
     379    const CanonicalPath &enum_prefix;
     380  };
     381  
     382  } // namespace Resolver
     383  } // namespace Rust
     384  
     385  #endif // RUST_AST_RESOLVE_STMT_H