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_LOWER_TYPE
      20  #define RUST_AST_LOWER_TYPE
      21  
      22  #include "rust-ast-lower-base.h"
      23  #include "rust-diagnostics.h"
      24  #include "rust-ast-lower-expr.h"
      25  
      26  namespace Rust {
      27  namespace HIR {
      28  
      29  class ASTLowerTypePath : public ASTLoweringBase
      30  {
      31  protected:
      32    using Rust::HIR::ASTLoweringBase::visit;
      33  
      34  public:
      35    static HIR::TypePath *translate (AST::TypePath &type);
      36  
      37    void visit (AST::TypePathSegmentFunction &segment) override;
      38    void visit (AST::TypePathSegment &segment) override;
      39    void visit (AST::TypePathSegmentGeneric &segment) override;
      40    void visit (AST::TypePath &path) override;
      41  
      42  protected:
      43    HIR::TypePathSegment *translated_segment;
      44  
      45  private:
      46    HIR::TypePath *translated;
      47  };
      48  
      49  class ASTLowerQualifiedPathInType : public ASTLowerTypePath
      50  {
      51    using ASTLowerTypePath::visit;
      52  
      53  public:
      54    static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type);
      55  
      56    void visit (AST::QualifiedPathInType &path) override;
      57  
      58  private:
      59    HIR::QualifiedPathInType *translated;
      60  };
      61  
      62  class ASTLoweringType : public ASTLoweringBase
      63  {
      64    using Rust::HIR::ASTLoweringBase::visit;
      65  
      66  public:
      67    static HIR::Type *translate (AST::Type *type)
      68    {
      69      ASTLoweringType resolver;
      70      type->accept_vis (resolver);
      71  
      72      rust_assert (resolver.translated != nullptr);
      73      resolver.mappings->insert_hir_type (resolver.translated);
      74      resolver.mappings->insert_location (
      75        resolver.translated->get_mappings ().get_hirid (),
      76        resolver.translated->get_locus ());
      77  
      78      return resolver.translated;
      79    }
      80  
      81    void visit (AST::BareFunctionType &fntype) override
      82    {
      83      bool is_variadic = false;
      84      std::vector<HIR::LifetimeParam> lifetime_params;
      85      HIR::FunctionQualifiers qualifiers
      86        = lower_qualifiers (fntype.get_function_qualifiers ());
      87  
      88      std::vector<HIR::MaybeNamedParam> named_params;
      89      for (auto ¶m : fntype.get_function_params ())
      90        {
      91  	HIR::MaybeNamedParam::ParamKind kind;
      92  	switch (param.get_param_kind ())
      93  	  {
      94  	  case AST::MaybeNamedParam::ParamKind::UNNAMED:
      95  	    kind = HIR::MaybeNamedParam::ParamKind::UNNAMED;
      96  	    break;
      97  	  case AST::MaybeNamedParam::ParamKind::IDENTIFIER:
      98  	    kind = HIR::MaybeNamedParam::ParamKind::IDENTIFIER;
      99  	    break;
     100  	  case AST::MaybeNamedParam::ParamKind::WILDCARD:
     101  	    kind = HIR::MaybeNamedParam::ParamKind::WILDCARD;
     102  	    break;
     103  	  default:
     104  	    gcc_unreachable ();
     105  	  }
     106  
     107  	HIR::Type *param_type
     108  	  = ASTLoweringType::translate (param.get_type ().get ());
     109  
     110  	HIR::MaybeNamedParam p (param.get_name (), kind,
     111  				std::unique_ptr<HIR::Type> (param_type),
     112  				param.get_locus ());
     113  	named_params.push_back (std::move (p));
     114        }
     115  
     116      HIR::Type *return_type = nullptr;
     117      if (fntype.has_return_type ())
     118        {
     119  	return_type
     120  	  = ASTLoweringType::translate (fntype.get_return_type ().get ());
     121        }
     122  
     123      auto crate_num = mappings->get_current_crate ();
     124      Analysis::NodeMapping mapping (crate_num, fntype.get_node_id (),
     125  				   mappings->get_next_hir_id (crate_num),
     126  				   mappings->get_next_localdef_id (crate_num));
     127  
     128      translated = new HIR::BareFunctionType (
     129        std::move (mapping), std::move (lifetime_params), std::move (qualifiers),
     130        std::move (named_params), is_variadic,
     131        std::unique_ptr<HIR::Type> (return_type), fntype.get_locus ());
     132    }
     133  
     134    void visit (AST::TupleType &tuple) override
     135    {
     136      std::vector<std::unique_ptr<HIR::Type>> elems;
     137      for (auto &e : tuple.get_elems ())
     138        {
     139  	HIR::Type *t = ASTLoweringType::translate (e.get ());
     140  	elems.push_back (std::unique_ptr<HIR::Type> (t));
     141        }
     142  
     143      auto crate_num = mappings->get_current_crate ();
     144      Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
     145  				   mappings->get_next_hir_id (crate_num),
     146  				   mappings->get_next_localdef_id (crate_num));
     147  
     148      translated = new HIR::TupleType (std::move (mapping), std::move (elems),
     149  				     tuple.get_locus ());
     150    }
     151  
     152    void visit (AST::TypePath &path) override
     153    {
     154      translated = ASTLowerTypePath::translate (path);
     155    }
     156  
     157    void visit (AST::QualifiedPathInType &path) override
     158    {
     159      translated = ASTLowerQualifiedPathInType::translate (path);
     160    }
     161  
     162    void visit (AST::ArrayType &type) override
     163    {
     164      HIR::Type *translated_type
     165        = ASTLoweringType::translate (type.get_elem_type ().get ());
     166      HIR::Expr *array_size
     167        = ASTLoweringExpr::translate (type.get_size_expr ().get ());
     168  
     169      auto crate_num = mappings->get_current_crate ();
     170      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     171  				   mappings->get_next_hir_id (crate_num),
     172  				   mappings->get_next_localdef_id (crate_num));
     173  
     174      translated
     175        = new HIR::ArrayType (mapping,
     176  			    std::unique_ptr<HIR::Type> (translated_type),
     177  			    std::unique_ptr<HIR::Expr> (array_size),
     178  			    type.get_locus ());
     179    }
     180  
     181    void visit (AST::ReferenceType &type) override
     182    {
     183      HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime ());
     184  
     185      HIR::Type *base_type
     186        = ASTLoweringType::translate (type.get_base_type ().get ());
     187  
     188      auto crate_num = mappings->get_current_crate ();
     189      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     190  				   mappings->get_next_hir_id (crate_num),
     191  				   mappings->get_next_localdef_id (crate_num));
     192  
     193      translated = new HIR::ReferenceType (mapping,
     194  					 type.get_has_mut () ? Mutability::Mut
     195  							     : Mutability::Imm,
     196  					 std::unique_ptr<HIR::Type> (base_type),
     197  					 type.get_locus (), lifetime);
     198    }
     199  
     200    void visit (AST::RawPointerType &type) override
     201    {
     202      HIR::Type *base_type
     203        = ASTLoweringType::translate (type.get_type_pointed_to ().get ());
     204  
     205      auto crate_num = mappings->get_current_crate ();
     206      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     207  				   mappings->get_next_hir_id (crate_num),
     208  				   mappings->get_next_localdef_id (crate_num));
     209  
     210      translated
     211        = new HIR::RawPointerType (mapping,
     212  				 type.get_pointer_type ()
     213  				     == AST::RawPointerType::PointerType::MUT
     214  				   ? Mutability::Mut
     215  				   : Mutability::Imm,
     216  				 std::unique_ptr<HIR::Type> (base_type),
     217  				 type.get_locus ());
     218    }
     219  
     220    void visit (AST::SliceType &type) override
     221    {
     222      HIR::Type *base_type
     223        = ASTLoweringType::translate (type.get_elem_type ().get ());
     224  
     225      auto crate_num = mappings->get_current_crate ();
     226      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     227  				   mappings->get_next_hir_id (crate_num),
     228  				   mappings->get_next_localdef_id (crate_num));
     229  
     230      translated
     231        = new HIR::SliceType (mapping, std::unique_ptr<HIR::Type> (base_type),
     232  			    type.get_locus ());
     233    }
     234  
     235    void visit (AST::InferredType &type) override
     236    {
     237      auto crate_num = mappings->get_current_crate ();
     238      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     239  				   mappings->get_next_hir_id (crate_num),
     240  				   mappings->get_next_localdef_id (crate_num));
     241  
     242      translated = new HIR::InferredType (mapping, type.get_locus ());
     243    }
     244  
     245    void visit (AST::NeverType &type) override
     246    {
     247      auto crate_num = mappings->get_current_crate ();
     248      Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
     249  				   mappings->get_next_hir_id (crate_num),
     250  				   mappings->get_next_localdef_id (crate_num));
     251  
     252      translated = new HIR::NeverType (mapping, type.get_locus ());
     253    }
     254  
     255    void visit (AST::TraitObjectTypeOneBound &type) override;
     256  
     257    void visit (AST::TraitObjectType &type) override;
     258  
     259  private:
     260    ASTLoweringType () : ASTLoweringBase (), translated (nullptr) {}
     261  
     262    HIR::Type *translated;
     263  };
     264  
     265  class ASTLowerGenericParam : public ASTLoweringBase
     266  {
     267    using Rust::HIR::ASTLoweringBase::visit;
     268  
     269  public:
     270    static HIR::GenericParam *translate (AST::GenericParam *param)
     271    {
     272      ASTLowerGenericParam resolver;
     273      param->accept_vis (resolver);
     274  
     275      rust_assert (resolver.translated != nullptr);
     276      resolver.mappings->insert_location (
     277        resolver.translated->get_mappings ().get_hirid (), param->get_locus ());
     278      resolver.mappings->insert_hir_generic_param (resolver.translated);
     279  
     280      return resolver.translated;
     281    }
     282  
     283    void visit (AST::LifetimeParam ¶m) override
     284    {
     285      auto crate_num = mappings->get_current_crate ();
     286      Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
     287  				   mappings->get_next_hir_id (crate_num),
     288  				   mappings->get_next_localdef_id (crate_num));
     289  
     290      HIR::Lifetime lt (mapping, param.get_lifetime ().get_lifetime_type (),
     291  		      param.get_lifetime ().get_lifetime_name (),
     292  		      param.get_lifetime ().get_locus ());
     293  
     294      translated = new HIR::LifetimeParam (mapping, lt, param.get_locus (),
     295  					 std::vector<Lifetime> ());
     296    }
     297  
     298    void visit (AST::ConstGenericParam ¶m) override
     299    {
     300      auto crate_num = mappings->get_current_crate ();
     301      Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
     302  				   mappings->get_next_hir_id (crate_num),
     303  				   mappings->get_next_localdef_id (crate_num));
     304  
     305      auto type = ASTLoweringType::translate (param.get_type ().get ());
     306  
     307      HIR::Expr *default_expr = nullptr;
     308      if (param.has_default_value ())
     309        default_expr = ASTLoweringExpr::translate (
     310  	param.get_default_value ().get_expression ().get ());
     311  
     312      translated
     313        = new HIR::ConstGenericParam (param.get_name (),
     314  				    std::unique_ptr<Type> (type),
     315  				    std::unique_ptr<Expr> (default_expr),
     316  				    mapping, param.get_locus ());
     317    }
     318  
     319    void visit (AST::TypeParam ¶m) override
     320    {
     321      AST::Attribute outer_attr = AST::Attribute::create_empty ();
     322      std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
     323      if (param.has_type_param_bounds ())
     324        {
     325  	for (auto &bound : param.get_type_param_bounds ())
     326  	  {
     327  	    HIR::TypeParamBound *lowered_bound = lower_bound (bound.get ());
     328  	    type_param_bounds.push_back (
     329  	      std::unique_ptr<HIR::TypeParamBound> (lowered_bound));
     330  	  }
     331        }
     332  
     333      HIR::Type *type = param.has_type ()
     334  			? ASTLoweringType::translate (param.get_type ().get ())
     335  			: nullptr;
     336  
     337      auto crate_num = mappings->get_current_crate ();
     338      Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
     339  				   mappings->get_next_hir_id (crate_num),
     340  				   mappings->get_next_localdef_id (crate_num));
     341  
     342      translated
     343        = new HIR::TypeParam (mapping, param.get_type_representation (),
     344  			    param.get_locus (), std::move (type_param_bounds),
     345  			    std::unique_ptr<Type> (type),
     346  			    std::move (outer_attr));
     347    }
     348  
     349  private:
     350    ASTLowerGenericParam () : ASTLoweringBase (), translated (nullptr) {}
     351  
     352    HIR::GenericParam *translated;
     353  };
     354  
     355  class ASTLoweringTypeBounds : public ASTLoweringBase
     356  {
     357    using Rust::HIR::ASTLoweringBase::visit;
     358  
     359  public:
     360    static HIR::TypeParamBound *translate (AST::TypeParamBound *type)
     361    {
     362      ASTLoweringTypeBounds resolver;
     363      type->accept_vis (resolver);
     364  
     365      rust_assert (resolver.translated != nullptr);
     366      resolver.mappings->insert_location (
     367        resolver.translated->get_mappings ().get_hirid (),
     368        resolver.translated->get_locus ());
     369  
     370      return resolver.translated;
     371    }
     372  
     373    void visit (AST::TraitBound &bound) override
     374    {
     375      // FIXME
     376      std::vector<HIR::LifetimeParam> lifetimes;
     377  
     378      AST::TypePath &ast_trait_path = bound.get_type_path ();
     379      HIR::TypePath *trait_path = ASTLowerTypePath::translate (ast_trait_path);
     380  
     381      auto crate_num = mappings->get_current_crate ();
     382      Analysis::NodeMapping mapping (crate_num, bound.get_node_id (),
     383  				   mappings->get_next_hir_id (crate_num),
     384  				   UNKNOWN_LOCAL_DEFID);
     385  
     386      translated = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (),
     387  				      bound.is_in_parens (),
     388  				      bound.has_opening_question_mark ());
     389    }
     390  
     391    void visit (AST::Lifetime &bound) override
     392    {
     393      HIR::Lifetime lifetime = lower_lifetime (bound);
     394      translated = new HIR::Lifetime (lifetime);
     395    }
     396  
     397  private:
     398    ASTLoweringTypeBounds () : ASTLoweringBase (), translated (nullptr) {}
     399  
     400    HIR::TypeParamBound *translated;
     401  };
     402  
     403  class ASTLowerWhereClauseItem : public ASTLoweringBase
     404  {
     405    using Rust::HIR::ASTLoweringBase::visit;
     406  
     407  public:
     408    static HIR::WhereClauseItem *translate (AST::WhereClauseItem &item)
     409    {
     410      ASTLowerWhereClauseItem compiler;
     411      item.accept_vis (compiler);
     412  
     413      rust_assert (compiler.translated != nullptr);
     414      // FIXME
     415      // compiler.mappings->insert_location (
     416      //   compiler.translated->get_mappings ().get_hirid (),
     417      //   compiler.translated->get_locus ());
     418  
     419      return compiler.translated;
     420    }
     421  
     422    void visit (AST::LifetimeWhereClauseItem &item) override
     423    {
     424      HIR::Lifetime l = lower_lifetime (item.get_lifetime ());
     425      std::vector<HIR::Lifetime> lifetime_bounds;
     426      for (auto &lifetime_bound : item.get_lifetime_bounds ())
     427        {
     428  	HIR::Lifetime ll = lower_lifetime (lifetime_bound);
     429  	lifetime_bounds.push_back (std::move (ll));
     430        }
     431  
     432      auto crate_num = mappings->get_current_crate ();
     433      Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
     434  				   mappings->get_next_hir_id (crate_num),
     435  				   UNKNOWN_LOCAL_DEFID);
     436  
     437      translated = new HIR::LifetimeWhereClauseItem (mapping, std::move (l),
     438  						   std::move (lifetime_bounds),
     439  						   item.get_locus ());
     440    }
     441  
     442    void visit (AST::TypeBoundWhereClauseItem &item) override
     443    {
     444      // FIXME
     445      std::vector<HIR::LifetimeParam> for_lifetimes;
     446  
     447      std::unique_ptr<HIR::Type> bound_type = std::unique_ptr<HIR::Type> (
     448        ASTLoweringType::translate (item.get_type ().get ()));
     449  
     450      std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
     451      for (auto &bound : item.get_type_param_bounds ())
     452        {
     453  	HIR::TypeParamBound *b
     454  	  = ASTLoweringTypeBounds::translate (bound.get ());
     455  	type_param_bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b));
     456        }
     457  
     458      auto crate_num = mappings->get_current_crate ();
     459      Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
     460  				   mappings->get_next_hir_id (crate_num),
     461  				   UNKNOWN_LOCAL_DEFID);
     462  
     463      translated
     464        = new HIR::TypeBoundWhereClauseItem (mapping, std::move (for_lifetimes),
     465  					   std::move (bound_type),
     466  					   std::move (type_param_bounds),
     467  					   item.get_locus ());
     468    }
     469  
     470  private:
     471    ASTLowerWhereClauseItem () : ASTLoweringBase (), translated (nullptr) {}
     472  
     473    HIR::WhereClauseItem *translated;
     474  };
     475  
     476  } // namespace HIR
     477  } // namespace Rust
     478  
     479  #endif // RUST_AST_LOWER_TYPE