LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-type.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 73.6 % 307 226
Test Date: 2026-02-28 14:20:25 Functions: 62.8 % 94 59
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 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_TYPE_H
      20              : #define RUST_AST_TYPE_H
      21              : 
      22              : #include "optional.h"
      23              : #include "rust-ast.h"
      24              : #include "rust-expr.h"
      25              : #include "rust-path.h"
      26              : 
      27              : namespace Rust {
      28              : namespace AST {
      29              : // definitions moved to rust-ast.h
      30              : class TypeParamBound;
      31              : class Lifetime;
      32              : 
      33              : // A trait bound
      34              : class TraitBound : public TypeParamBound
      35              : {
      36              :   bool in_parens;
      37              :   bool opening_question_mark;
      38              : 
      39              :   // bool has_for_lifetimes;
      40              :   // LifetimeParams for_lifetimes;
      41              :   std::vector<LifetimeParam> for_lifetimes; // inlined LifetimeParams
      42              : 
      43              :   TypePath type_path;
      44              : 
      45              :   location_t locus;
      46              : 
      47              : public:
      48              :   // Returns whether trait bound has "for" lifetimes
      49          426 :   bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
      50              : 
      51        30422 :   std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
      52              : 
      53              :   const std::vector<LifetimeParam> &get_for_lifetimes () const
      54              :   {
      55            2 :     return for_lifetimes;
      56              :   }
      57              : 
      58         2018 :   TraitBound (TypePath type_path, location_t locus, bool in_parens = false,
      59              :               bool opening_question_mark = false,
      60              :               std::vector<LifetimeParam> for_lifetimes
      61              :               = std::vector<LifetimeParam> ())
      62         2018 :     : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
      63         2018 :       in_parens (in_parens), opening_question_mark (opening_question_mark),
      64         2018 :       for_lifetimes (std::move (for_lifetimes)),
      65         2018 :       type_path (std::move (type_path)), locus (locus)
      66         2018 :   {}
      67              : 
      68         1807 :   TraitBound (NodeId id, TypePath type_path, location_t locus,
      69              :               bool in_parens = false, bool opening_question_mark = false,
      70              :               std::vector<LifetimeParam> for_lifetimes
      71              :               = std::vector<LifetimeParam> ())
      72         1807 :     : TypeParamBound (id), in_parens (in_parens),
      73         1807 :       opening_question_mark (opening_question_mark),
      74         1807 :       for_lifetimes (std::move (for_lifetimes)),
      75         1807 :       type_path (std::move (type_path)), locus (locus)
      76         1807 :   {}
      77              : 
      78          645 :   TraitBound (TraitBound const &other)
      79          645 :     : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens),
      80          645 :       opening_question_mark (other.opening_question_mark),
      81          645 :       for_lifetimes (other.for_lifetimes), type_path (other.type_path),
      82          645 :       locus (other.locus)
      83          645 :   {}
      84              : 
      85              :   std::string as_string () const override;
      86              : 
      87         1869 :   location_t get_locus () const override final { return locus; }
      88              : 
      89              :   void accept_vis (ASTVisitor &vis) override;
      90              : 
      91              :   // TODO: this mutable getter seems kinda dodgy
      92        37812 :   TypePath &get_type_path () { return type_path; }
      93            2 :   const TypePath &get_type_path () const { return type_path; }
      94              : 
      95         1818 :   bool is_in_parens () const { return in_parens; }
      96         2244 :   bool has_opening_question_mark () const { return opening_question_mark; }
      97              : 
      98           93 :   TypeParamBoundType get_bound_type () const override
      99              :   {
     100           93 :     return TypeParamBound::TypeParamBoundType::TRAIT;
     101              :   }
     102              : 
     103              : protected:
     104              :   /* Use covariance to implement clone function as returning this object rather
     105              :    * than base */
     106         1807 :   TraitBound *clone_type_param_bound_impl () const override
     107              :   {
     108         5421 :     return new TraitBound (node_id, type_path, locus, in_parens,
     109         1807 :                            opening_question_mark, for_lifetimes);
     110              :   }
     111            0 :   TraitBound *reconstruct_impl () const override
     112              :   {
     113            0 :     return new TraitBound (type_path, locus, in_parens, opening_question_mark,
     114            0 :                            for_lifetimes);
     115              :   }
     116              : };
     117              : 
     118              : // definition moved to rust-ast.h
     119              : class TypeNoBounds;
     120              : 
     121              : // An impl trait? Poor reference material here.
     122              : class ImplTraitType : public Type
     123              : {
     124              :   // TypeParamBounds type_param_bounds;
     125              :   // inlined form
     126              :   std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
     127              : 
     128              :   location_t locus;
     129              : 
     130              : protected:
     131              :   /* Use covariance to implement clone function as returning this object rather
     132              :    * than base */
     133            0 :   ImplTraitType *clone_type_impl () const override
     134              :   {
     135            0 :     return new ImplTraitType (*this);
     136              :   }
     137            0 :   ImplTraitType *reconstruct_impl () const override
     138              :   {
     139            0 :     return new ImplTraitType (reconstruct_vec (type_param_bounds), locus);
     140              :   }
     141              : 
     142              : public:
     143            0 :   ImplTraitType (
     144              :     std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
     145              :     location_t locus)
     146            0 :     : type_param_bounds (std::move (type_param_bounds)), locus (locus)
     147            0 :   {}
     148              : 
     149              :   // copy constructor with vector clone
     150            0 :   ImplTraitType (ImplTraitType const &other)
     151            0 :     : Type (other.node_id), locus (other.locus)
     152              :   {
     153            0 :     type_param_bounds.reserve (other.type_param_bounds.size ());
     154            0 :     for (const auto &e : other.type_param_bounds)
     155            0 :       type_param_bounds.push_back (e->clone_type_param_bound ());
     156            0 :   }
     157              : 
     158              :   // overloaded assignment operator to clone
     159              :   ImplTraitType &operator= (ImplTraitType const &other)
     160              :   {
     161              :     locus = other.locus;
     162              : 
     163              :     type_param_bounds.reserve (other.type_param_bounds.size ());
     164              :     for (const auto &e : other.type_param_bounds)
     165              :       type_param_bounds.push_back (e->clone_type_param_bound ());
     166              : 
     167              :     return *this;
     168              :   }
     169              : 
     170              :   // move constructors
     171              :   ImplTraitType (ImplTraitType &&other) = default;
     172              :   ImplTraitType &operator= (ImplTraitType &&other) = default;
     173              : 
     174              :   std::string as_string () const override;
     175              : 
     176            0 :   location_t get_locus () const override final { return locus; }
     177              : 
     178              :   void accept_vis (ASTVisitor &vis) override;
     179              : 
     180            0 :   std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
     181              :   {
     182            0 :     return type_param_bounds;
     183              :   }
     184              :   const std::vector<std::unique_ptr<TypeParamBound> > &
     185              :   get_type_param_bounds () const
     186              :   {
     187              :     return type_param_bounds;
     188              :   }
     189              : 
     190            0 :   Type::Kind get_type_kind () const override { return Type::Kind::ImplTrait; }
     191              : };
     192              : 
     193              : // An opaque value of another type that implements a set of traits
     194              : class TraitObjectType : public Type
     195              : {
     196              :   bool has_dyn;
     197              :   std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
     198              :   location_t locus;
     199              : 
     200              : protected:
     201              :   /* Use covariance to implement clone function as returning this object rather
     202              :    * than base */
     203           13 :   TraitObjectType *clone_type_impl () const override
     204              :   {
     205           13 :     return new TraitObjectType (*this);
     206              :   }
     207            0 :   TraitObjectType *reconstruct_impl () const override
     208              :   {
     209            0 :     return new TraitObjectType (reconstruct_vec (type_param_bounds), locus,
     210            0 :                                 has_dyn);
     211              :   }
     212              : 
     213              : public:
     214           14 :   TraitObjectType (
     215              :     std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
     216              :     location_t locus, bool is_dyn_dispatch)
     217           28 :     : has_dyn (is_dyn_dispatch),
     218           14 :       type_param_bounds (std::move (type_param_bounds)), locus (locus)
     219              :   {}
     220              : 
     221              :   // copy constructor with vector clone
     222           13 :   TraitObjectType (TraitObjectType const &other)
     223           13 :     : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
     224              :   {
     225           13 :     type_param_bounds.reserve (other.type_param_bounds.size ());
     226           46 :     for (const auto &e : other.type_param_bounds)
     227           33 :       type_param_bounds.push_back (e->clone_type_param_bound ());
     228           13 :   }
     229              : 
     230              :   // overloaded assignment operator to clone
     231              :   TraitObjectType &operator= (TraitObjectType const &other)
     232              :   {
     233              :     has_dyn = other.has_dyn;
     234              :     locus = other.locus;
     235              :     type_param_bounds.reserve (other.type_param_bounds.size ());
     236              :     for (const auto &e : other.type_param_bounds)
     237              :       type_param_bounds.push_back (e->clone_type_param_bound ());
     238              : 
     239              :     return *this;
     240              :   }
     241              : 
     242              :   // move constructors
     243              :   TraitObjectType (TraitObjectType &&other) = default;
     244              :   TraitObjectType &operator= (TraitObjectType &&other) = default;
     245              : 
     246              :   std::string as_string () const override;
     247              : 
     248           36 :   location_t get_locus () const override final { return locus; }
     249              : 
     250              :   void accept_vis (ASTVisitor &vis) override;
     251              : 
     252           11 :   bool is_dyn () const { return has_dyn; }
     253              : 
     254            0 :   std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
     255              :   {
     256          210 :     return type_param_bounds;
     257              :   }
     258              :   const std::vector<std::unique_ptr<TypeParamBound> > &
     259              :   get_type_param_bounds () const
     260              :   {
     261              :     return type_param_bounds;
     262              :   }
     263              : 
     264            0 :   Type::Kind get_type_kind () const override { return Type::Kind::TraitObject; }
     265              : };
     266              : 
     267              : // A type with parentheses around it, used to avoid ambiguity.
     268              : class ParenthesisedType : public TypeNoBounds
     269              : {
     270              :   std::unique_ptr<Type> type_in_parens;
     271              :   location_t locus;
     272              : 
     273              : protected:
     274              :   /* Use covariance to implement clone function as returning this object rather
     275              :    * than base */
     276            7 :   ParenthesisedType *clone_type_no_bounds_impl () const override
     277              :   {
     278            7 :     return new ParenthesisedType (*this);
     279              :   }
     280            0 :   ParenthesisedType *reconstruct_impl () const override
     281              :   {
     282            0 :     return new ParenthesisedType (type_in_parens->reconstruct (), locus);
     283              :   }
     284              : 
     285              : public:
     286              :   // Constructor uses Type pointer for polymorphism
     287            8 :   ParenthesisedType (std::unique_ptr<Type> type_inside_parens, location_t locus)
     288            8 :     : type_in_parens (std::move (type_inside_parens)), locus (locus)
     289              :   {}
     290              : 
     291              :   /* Copy constructor uses custom deep copy method for type to preserve
     292              :    * polymorphism */
     293            7 :   ParenthesisedType (ParenthesisedType const &other)
     294            7 :     : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus)
     295            7 :   {}
     296              : 
     297              :   // overload assignment operator to use custom clone method
     298              :   ParenthesisedType &operator= (ParenthesisedType const &other)
     299              :   {
     300              :     type_in_parens = other.type_in_parens->clone_type ();
     301              :     locus = other.locus;
     302              :     return *this;
     303              :   }
     304              : 
     305              :   // default move semantics
     306              :   ParenthesisedType (ParenthesisedType &&other) = default;
     307              :   ParenthesisedType &operator= (ParenthesisedType &&other) = default;
     308              : 
     309            0 :   std::string as_string () const override
     310              :   {
     311            0 :     return "(" + type_in_parens->as_string () + ")";
     312              :   }
     313              : 
     314              :   // Creates a trait bound (clone of this one's trait bound) - HACK
     315            0 :   TraitBound *to_trait_bound (bool) const override
     316              :   {
     317              :     /* NOTE: obviously it is unknown whether the internal type is a trait bound
     318              :      * due to polymorphism, so just let the internal type handle it. As
     319              :      * parenthesised type, it must be in parentheses. */
     320            0 :     return type_in_parens->to_trait_bound (true);
     321              :   }
     322              : 
     323           21 :   location_t get_locus () const override final { return locus; }
     324              : 
     325              :   void accept_vis (ASTVisitor &vis) override;
     326              : 
     327              :   // TODO: would a "vis_type" be better?
     328          151 :   std::unique_ptr<Type> &get_type_in_parens ()
     329              :   {
     330          151 :     rust_assert (type_in_parens != nullptr);
     331          151 :     return type_in_parens;
     332              :   }
     333              : 
     334            0 :   Type::Kind get_type_kind () const override
     335              :   {
     336            0 :     return Type::Kind::Parenthesised;
     337              :   }
     338              : };
     339              : 
     340              : // Impl trait with a single bound? Poor reference material here.
     341              : class ImplTraitTypeOneBound : public TypeNoBounds
     342              : {
     343              :   std::unique_ptr<TypeParamBound> trait_bound;
     344              :   location_t locus;
     345              : 
     346              : public:
     347          134 :   ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound,
     348              :                          location_t locus)
     349          134 :     : trait_bound (std::move (trait_bound)), locus (locus)
     350              :   {}
     351              : 
     352          170 :   ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other)
     353          510 :     : trait_bound (other.trait_bound->clone_type_param_bound ()),
     354          170 :       locus (other.locus)
     355          170 :   {}
     356              : 
     357              :   std::string as_string () const override;
     358              : 
     359          545 :   location_t get_locus () const override final { return locus; }
     360              : 
     361              :   void accept_vis (ASTVisitor &vis) override;
     362              : 
     363         1726 :   std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; }
     364              : 
     365          170 :   TypeNoBounds *clone_type_no_bounds_impl () const override
     366              :   {
     367          170 :     return new ImplTraitTypeOneBound (*this);
     368              :   }
     369            0 :   TypeNoBounds *reconstruct_impl () const override
     370              :   {
     371            0 :     return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
     372              :   }
     373              : 
     374            0 :   Type::Kind get_type_kind () const override
     375              :   {
     376            0 :     return Type::Kind::ImplTraitTypeOneBound;
     377              :   }
     378              : };
     379              : 
     380              : /* A trait object with a single trait bound. The "trait bound" is really just
     381              :  * the trait. Basically like using an interface as a type in an OOP language. */
     382              : class TraitObjectTypeOneBound : public TypeNoBounds
     383              : {
     384              :   bool has_dyn;
     385              :   TraitBound trait_bound;
     386              :   location_t locus;
     387              : 
     388              : protected:
     389              :   /* Use covariance to implement clone function as returning this object rather
     390              :    * than base */
     391          163 :   TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override
     392              :   {
     393          163 :     return new TraitObjectTypeOneBound (*this);
     394              :   }
     395            0 :   TraitObjectTypeOneBound *reconstruct_impl () const override
     396              :   {
     397            0 :     return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn);
     398              :   }
     399              : 
     400              : public:
     401          157 :   TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
     402              :                            bool is_dyn_dispatch = false)
     403          314 :     : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)),
     404          157 :       locus (locus)
     405              :   {}
     406              : 
     407              :   std::string as_string () const override;
     408              : 
     409              :   // Creates a trait bound (clone of this one's trait bound) - HACK
     410            0 :   TraitBound *to_trait_bound (bool) const override
     411              :   {
     412              :     /* NOTE: this assumes there is no dynamic dispatch specified- if there was,
     413              :      * this cloning would not be required as parsing is unambiguous. */
     414            0 :     return new TraitBound (trait_bound);
     415              :   }
     416              : 
     417          308 :   location_t get_locus () const override final { return locus; }
     418              : 
     419              :   void accept_vis (ASTVisitor &vis) override;
     420              : 
     421              :   // TODO: would a "vis_type" be better?
     422         2638 :   TraitBound &get_trait_bound ()
     423              :   {
     424              :     // TODO: check to ensure invariants are met?
     425         2638 :     return trait_bound;
     426              :   }
     427              : 
     428          266 :   bool is_dyn () const { return has_dyn; }
     429              : 
     430            0 :   Type::Kind get_type_kind () const override
     431              :   {
     432            0 :     return Type::Kind::TraitObjectTypeOneBound;
     433              :   }
     434              : };
     435              : 
     436              : class TypePath; // definition moved to "rust-path.h"
     437              : 
     438              : /* A type consisting of the "product" of others (the tuple's elements) in a
     439              :  * specific order */
     440              : class TupleType : public TypeNoBounds
     441              : {
     442              :   std::vector<std::unique_ptr<Type> > elems;
     443              :   location_t locus;
     444              : 
     445              : public:
     446              :   // Returns whether the tuple type is the unit type, i.e. has no elements.
     447            0 :   bool is_unit_type () const { return elems.empty (); }
     448              : 
     449          407 :   TupleType (std::vector<std::unique_ptr<Type> > elems, location_t locus)
     450          407 :     : elems (std::move (elems)), locus (locus)
     451          407 :   {}
     452              : 
     453              :   // copy constructor with vector clone
     454          838 :   TupleType (TupleType const &other) : locus (other.locus)
     455              :   {
     456          838 :     elems.reserve (other.elems.size ());
     457         2229 :     for (const auto &e : other.elems)
     458         1391 :       elems.push_back (e->clone_type ());
     459          838 :   }
     460              : 
     461              :   // overloaded assignment operator to clone
     462              :   TupleType &operator= (TupleType const &other)
     463              :   {
     464              :     locus = other.locus;
     465              : 
     466              :     elems.reserve (other.elems.size ());
     467              :     for (const auto &e : other.elems)
     468              :       elems.push_back (e->clone_type ());
     469              : 
     470              :     return *this;
     471              :   }
     472              : 
     473              :   // move constructors
     474              :   TupleType (TupleType &&other) = default;
     475              :   TupleType &operator= (TupleType &&other) = default;
     476              : 
     477              :   std::string as_string () const override;
     478              : 
     479          416 :   location_t get_locus () const override final { return locus; }
     480              : 
     481              :   void accept_vis (ASTVisitor &vis) override;
     482              : 
     483         9539 :   std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
     484              :   const std::vector<std::unique_ptr<Type> > &get_elems () const
     485              :   {
     486              :     return elems;
     487              :   }
     488              : 
     489              : protected:
     490              :   /* Use covariance to implement clone function as returning this object rather
     491              :    * than base */
     492          838 :   TupleType *clone_type_no_bounds_impl () const override
     493              :   {
     494          838 :     return new TupleType (*this);
     495              :   }
     496            0 :   TupleType *reconstruct_impl () const override
     497              :   {
     498            0 :     return new TupleType (reconstruct_vec (elems), locus);
     499              :   }
     500              : 
     501            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Tuple; }
     502              : };
     503              : 
     504              : /* A type with no values, representing the result of computations that never
     505              :  * complete. Expressions of NeverType can be coerced into any other types.
     506              :  * Represented as "!". */
     507           47 : class NeverType : public TypeNoBounds
     508              : {
     509              :   location_t locus;
     510              : 
     511              : protected:
     512              :   /* Use covariance to implement clone function as returning this object rather
     513              :    * than base */
     514           47 :   NeverType *clone_type_no_bounds_impl () const override
     515              :   {
     516           47 :     return new NeverType (*this);
     517              :   }
     518            0 :   NeverType *reconstruct_impl () const override
     519              :   {
     520            0 :     return new NeverType (locus);
     521              :   }
     522              : 
     523              : public:
     524           47 :   NeverType (location_t locus) : locus (locus) {}
     525              : 
     526            0 :   std::string as_string () const override { return "! (never type)"; }
     527              : 
     528           60 :   location_t get_locus () const override final { return locus; }
     529              : 
     530              :   void accept_vis (ASTVisitor &vis) override;
     531              : 
     532            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Never; }
     533              : };
     534              : 
     535              : // A type consisting of a pointer without safety or liveness guarantees
     536              : class RawPointerType : public TypeNoBounds
     537              : {
     538              : public:
     539              :   enum PointerType
     540              :   {
     541              :     MUT,
     542              :     CONST
     543              :   };
     544              : 
     545              : private:
     546              :   PointerType pointer_type;
     547              :   std::unique_ptr<TypeNoBounds> type;
     548              :   location_t locus;
     549              : 
     550              : public:
     551              :   // Returns whether the pointer is mutable or constant.
     552         6763 :   PointerType get_pointer_type () const { return pointer_type; }
     553              : 
     554              :   // Constructor requires pointer for polymorphism reasons
     555         6540 :   RawPointerType (PointerType pointer_type,
     556              :                   std::unique_ptr<TypeNoBounds> type_no_bounds,
     557              :                   location_t locus)
     558        13080 :     : pointer_type (pointer_type), type (std::move (type_no_bounds)),
     559         6540 :       locus (locus)
     560              :   {}
     561              : 
     562              :   // Copy constructor calls custom polymorphic clone function
     563         7182 :   RawPointerType (RawPointerType const &other)
     564        14364 :     : pointer_type (other.pointer_type),
     565         7182 :       type (other.type->clone_type_no_bounds ()), locus (other.locus)
     566         7182 :   {}
     567              : 
     568              :   // overload assignment operator to use custom clone method
     569              :   RawPointerType &operator= (RawPointerType const &other)
     570              :   {
     571              :     pointer_type = other.pointer_type;
     572              :     type = other.type->clone_type_no_bounds ();
     573              :     locus = other.locus;
     574              :     return *this;
     575              :   }
     576              : 
     577              :   // default move semantics
     578              :   RawPointerType (RawPointerType &&other) = default;
     579              :   RawPointerType &operator= (RawPointerType &&other) = default;
     580              : 
     581              :   std::string as_string () const override;
     582              : 
     583         7959 :   location_t get_locus () const override final { return locus; }
     584              : 
     585              :   void accept_vis (ASTVisitor &vis) override;
     586              : 
     587              :   // TODO: would a "vis_type" be better?
     588       167970 :   TypeNoBounds &get_type_pointed_to ()
     589              :   {
     590       167970 :     rust_assert (type != nullptr);
     591       167970 :     return *type;
     592              :   }
     593              : 
     594        21298 :   std::unique_ptr<TypeNoBounds> &get_type_pointed_to_ptr ()
     595              :   {
     596        21298 :     rust_assert (type != nullptr);
     597        21298 :     return type;
     598              :   }
     599              : 
     600              :   // Getter for direct access to the type unique_ptr
     601            0 :   std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
     602              : 
     603              : protected:
     604              :   /* Use covariance to implement clone function as returning this object rather
     605              :    * than base */
     606         7182 :   RawPointerType *clone_type_no_bounds_impl () const override
     607              :   {
     608         7182 :     return new RawPointerType (*this);
     609              :   }
     610            0 :   RawPointerType *reconstruct_impl () const override
     611              :   {
     612            0 :     return new RawPointerType (pointer_type, type->reconstruct (), locus);
     613              :   }
     614              : 
     615         1042 :   Type::Kind get_type_kind () const override { return Type::Kind::RawPointer; }
     616              : };
     617              : 
     618              : // A type pointing to memory owned by another value
     619              : class ReferenceType : public TypeNoBounds
     620              : {
     621              :   // bool has_lifetime; // TODO: handle in lifetime or something?
     622              :   tl::optional<Lifetime> lifetime;
     623              : 
     624              :   bool has_mut;
     625              :   std::unique_ptr<TypeNoBounds> type;
     626              :   location_t locus;
     627              : 
     628              : public:
     629              :   // Returns whether the reference is mutable or immutable.
     630              :   bool is_mut () const { return has_mut; }
     631              : 
     632              :   // Returns whether the reference has a lifetime.
     633          686 :   bool has_lifetime () const { return lifetime.has_value (); }
     634              : 
     635              :   // Constructor
     636         4503 :   ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
     637              :                  location_t locus,
     638              :                  tl::optional<Lifetime> lifetime = Lifetime::elided ())
     639        13509 :     : lifetime (std::move (lifetime)), has_mut (is_mut),
     640         4503 :       type (std::move (type_no_bounds)), locus (locus)
     641              :   {}
     642              : 
     643              :   // Copy constructor with custom clone method
     644         7593 :   ReferenceType (ReferenceType const &other)
     645        22779 :     : lifetime (other.lifetime), has_mut (other.has_mut),
     646         7593 :       type (other.type->clone_type_no_bounds ()), locus (other.locus)
     647         7593 :   {}
     648              : 
     649              :   // Operator overload assignment operator to custom clone the unique pointer
     650              :   ReferenceType &operator= (ReferenceType const &other)
     651              :   {
     652              :     lifetime = other.lifetime;
     653              :     has_mut = other.has_mut;
     654              :     type = other.type->clone_type_no_bounds ();
     655              :     locus = other.locus;
     656              : 
     657              :     return *this;
     658              :   }
     659              : 
     660              :   // move constructors
     661              :   ReferenceType (ReferenceType &&other) = default;
     662              :   ReferenceType &operator= (ReferenceType &&other) = default;
     663              : 
     664              :   std::string as_string () const override;
     665              : 
     666         6628 :   location_t get_locus () const override final { return locus; }
     667              : 
     668              :   void accept_vis (ASTVisitor &vis) override;
     669              : 
     670              :   // TODO: would a "vis_type" be better?
     671        36621 :   TypeNoBounds &get_type_referenced ()
     672              :   {
     673        36621 :     rust_assert (type != nullptr);
     674        36621 :     return *type;
     675              :   }
     676              : 
     677              :   std::unique_ptr<TypeNoBounds> &get_type_referenced_ptr ()
     678              :   {
     679              :     rust_assert (type != nullptr);
     680              :     return type;
     681              :   }
     682              : 
     683         5065 :   bool get_has_mut () const { return has_mut; }
     684              : 
     685        97075 :   Lifetime &get_lifetime () { return lifetime.value (); }
     686            0 :   const Lifetime &get_lifetime () const { return lifetime.value (); }
     687              : 
     688        81173 :   TypeNoBounds &get_base_type () { return *type; }
     689              : 
     690              :   // Getter for direct access to the type unique_ptr
     691        15230 :   std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
     692              : 
     693              : protected:
     694              :   /* Use covariance to implement clone function as returning this object rather
     695              :    * than base */
     696         7593 :   ReferenceType *clone_type_no_bounds_impl () const override
     697              :   {
     698         7593 :     return new ReferenceType (*this);
     699              :   }
     700            0 :   ReferenceType *reconstruct_impl () const override
     701              :   {
     702            0 :     return new ReferenceType (has_mut, type->reconstruct (), locus,
     703              :                               // TODO: Improve this - it's ugly!
     704            0 :                               has_lifetime () ? tl::make_optional<Lifetime> (
     705            0 :                                 lifetime->get_lifetime_type (),
     706            0 :                                 lifetime->get_lifetime_name (),
     707            0 :                                 lifetime->get_locus ())
     708            0 :                                               : tl::nullopt);
     709              :   }
     710              : 
     711            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Reference; }
     712              : };
     713              : 
     714              : // A fixed-size sequence of elements of a specified type
     715              : class ArrayType : public TypeNoBounds
     716              : {
     717              :   std::unique_ptr<Type> elem_type;
     718              :   AnonConst size;
     719              :   location_t locus;
     720              : 
     721              : public:
     722              :   // Constructor requires pointers for polymorphism
     723          667 :   ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
     724          667 :     : elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
     725          667 :   {}
     726              : 
     727              :   // Copy constructor requires deep copies of both unique pointers
     728         1984 :   ArrayType (ArrayType const &other)
     729         1984 :     : elem_type (other.elem_type->clone_type ()), size (other.size),
     730         1984 :       locus (other.locus)
     731         1984 :   {}
     732              : 
     733              :   // Overload assignment operator to deep copy pointers
     734              :   ArrayType &operator= (ArrayType const &other)
     735              :   {
     736              :     elem_type = other.elem_type->clone_type ();
     737              :     size = other.size;
     738              :     locus = other.locus;
     739              :     return *this;
     740              :   }
     741              : 
     742              :   // move constructors
     743              :   ArrayType (ArrayType &&other) = default;
     744              :   ArrayType &operator= (ArrayType &&other) = default;
     745              : 
     746              :   std::string as_string () const override;
     747              : 
     748          690 :   location_t get_locus () const override final { return locus; }
     749              : 
     750              :   void accept_vis (ASTVisitor &vis) override;
     751              : 
     752              :   // TODO: would a "vis_type" be better?
     753        17000 :   Type &get_elem_type ()
     754              :   {
     755        17000 :     rust_assert (elem_type != nullptr);
     756        17000 :     return *elem_type;
     757              :   }
     758              : 
     759         2240 :   std::unique_ptr<Type> &get_elem_type_ptr ()
     760              :   {
     761         2240 :     rust_assert (elem_type != nullptr);
     762         2240 :     return elem_type;
     763              :   }
     764              : 
     765              :   // TODO: would a "vis_expr" be better?
     766        18577 :   AnonConst &get_size_expr ()
     767              :   {
     768              :     // rust_assert (size != nullptr);
     769              : 
     770        18577 :     return size;
     771              :   }
     772              : 
     773          371 :   std::unique_ptr<Type> &get_element_type () { return elem_type; }
     774              : 
     775              : protected:
     776              :   /* Use covariance to implement clone function as returning this object rather
     777              :    * than base */
     778         1984 :   ArrayType *clone_type_no_bounds_impl () const override
     779              :   {
     780         1984 :     return new ArrayType (*this);
     781              :   }
     782            0 :   ArrayType *reconstruct_impl () const override
     783              :   {
     784            0 :     return new ArrayType (elem_type->reconstruct (),
     785            0 :                           size /* FIXME: This should be `reconstruct_expr()` */,
     786            0 :                           locus);
     787              :   }
     788              : 
     789            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Array; }
     790              : };
     791              : 
     792              : /* A dynamically-sized type representing a "view" into a sequence of elements of
     793              :  * a type */
     794              : class SliceType : public TypeNoBounds
     795              : {
     796              :   std::unique_ptr<Type> elem_type;
     797              :   location_t locus;
     798              : 
     799              : public:
     800              :   // Constructor requires pointer for polymorphism
     801          842 :   SliceType (std::unique_ptr<Type> type, location_t locus)
     802          842 :     : elem_type (std::move (type)), locus (locus)
     803              :   {}
     804              : 
     805              :   // Copy constructor requires deep copy of Type smart pointer
     806         1195 :   SliceType (SliceType const &other)
     807         1195 :     : elem_type (other.elem_type->clone_type ()), locus (other.locus)
     808         1195 :   {}
     809              : 
     810              :   // Overload assignment operator to deep copy
     811              :   SliceType &operator= (SliceType const &other)
     812              :   {
     813              :     elem_type = other.elem_type->clone_type ();
     814              :     locus = other.locus;
     815              : 
     816              :     return *this;
     817              :   }
     818              : 
     819              :   // move constructors
     820              :   SliceType (SliceType &&other) = default;
     821              :   SliceType &operator= (SliceType &&other) = default;
     822              : 
     823              :   std::string as_string () const override;
     824              : 
     825         1362 :   location_t get_locus () const override final { return locus; }
     826              : 
     827              :   void accept_vis (ASTVisitor &vis) override;
     828              : 
     829              :   // TODO: would a "vis_type" be better?
     830        17246 :   Type &get_elem_type ()
     831              :   {
     832        17246 :     rust_assert (elem_type != nullptr);
     833        17246 :     return *elem_type;
     834              :   }
     835              : 
     836              :   // Getter for direct access to the elem_type unique_ptr
     837         2593 :   std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
     838              : 
     839              : protected:
     840              :   /* Use covariance to implement clone function as returning this object
     841              :    * rather than base */
     842         1195 :   SliceType *clone_type_no_bounds_impl () const override
     843              :   {
     844         1195 :     return new SliceType (*this);
     845              :   }
     846            0 :   SliceType *reconstruct_impl () const override
     847              :   {
     848            0 :     return new SliceType (elem_type->reconstruct (), locus);
     849              :   }
     850              : 
     851            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Slice; }
     852              : };
     853              : 
     854              : /* Type used in generic arguments to explicitly request type inference (wildcard
     855              :  * pattern) */
     856          322 : class InferredType : public TypeNoBounds
     857              : {
     858              :   location_t locus;
     859              : 
     860              :   // e.g. Vec<_> = whatever
     861              : protected:
     862              :   /* Use covariance to implement clone function as returning this object
     863              :    * rather than base */
     864          322 :   InferredType *clone_type_no_bounds_impl () const override
     865              :   {
     866              :     // This goes through the copy constructor
     867          322 :     return new InferredType (*this);
     868              :   }
     869              : 
     870            0 :   InferredType *reconstruct_impl () const override
     871              :   {
     872              :     // This goes through the base constructor which calls the base
     873              :     // TypeNoBounds constructor, which allocates a new NodeId
     874            0 :     return new InferredType (locus);
     875              :   }
     876              : 
     877              : public:
     878          208 :   InferredType (location_t locus) : locus (locus) {}
     879              : 
     880              :   std::string as_string () const override;
     881              : 
     882          271 :   location_t get_locus () const override final { return locus; }
     883              : 
     884              :   void accept_vis (ASTVisitor &vis) override;
     885              : 
     886            0 :   Type::Kind get_type_kind () const override { return Type::Kind::Inferred; }
     887              : };
     888              : 
     889              : class QualifiedPathInType; // definition moved to "rust-path.h"
     890              : 
     891              : // A possibly named param used in a BaseFunctionType
     892              : struct MaybeNamedParam
     893              : {
     894              : public:
     895              :   enum ParamKind
     896              :   {
     897              :     UNNAMED,
     898              :     IDENTIFIER,
     899              :     WILDCARD
     900              :   };
     901              : 
     902              : private:
     903              :   std::vector<Attribute> outer_attrs;
     904              : 
     905              :   std::unique_ptr<Type> param_type;
     906              : 
     907              :   ParamKind param_kind;
     908              :   Identifier name; // technically, can be an identifier or '_'
     909              : 
     910              :   location_t locus;
     911              : 
     912              : public:
     913           48 :   MaybeNamedParam (Identifier name, ParamKind param_kind,
     914              :                    std::unique_ptr<Type> param_type,
     915              :                    std::vector<Attribute> outer_attrs, location_t locus)
     916           48 :     : outer_attrs (std::move (outer_attrs)),
     917           48 :       param_type (std::move (param_type)), param_kind (param_kind),
     918           48 :       name (std::move (name)), locus (locus)
     919           48 :   {}
     920              : 
     921              :   // Copy constructor with clone
     922           54 :   MaybeNamedParam (MaybeNamedParam const &other)
     923           54 :     : outer_attrs (other.outer_attrs), param_kind (other.param_kind),
     924           54 :       name (other.name), locus (other.locus)
     925              :   {
     926              :     // guard to prevent null dereference
     927           54 :     if (other.param_type != nullptr)
     928           54 :       param_type = other.param_type->clone_type ();
     929           54 :   }
     930              : 
     931          108 :   ~MaybeNamedParam () = default;
     932              : 
     933              :   // Overloaded assignment operator with clone
     934              :   MaybeNamedParam &operator= (MaybeNamedParam const &other)
     935              :   {
     936              :     outer_attrs = other.outer_attrs;
     937              :     name = other.name;
     938              :     param_kind = other.param_kind;
     939              :     locus = other.locus;
     940              : 
     941              :     // guard to prevent null dereference
     942              :     if (other.param_type != nullptr)
     943              :       param_type = other.param_type->clone_type ();
     944              :     else
     945              :       param_type = nullptr;
     946              : 
     947              :     return *this;
     948              :   }
     949              : 
     950              :   // move constructors
     951           54 :   MaybeNamedParam (MaybeNamedParam &&other) = default;
     952            0 :   MaybeNamedParam &operator= (MaybeNamedParam &&other) = default;
     953              : 
     954              :   std::string as_string () const;
     955              : 
     956              :   // Returns whether the param is in an error state.
     957           48 :   bool is_error () const { return param_type == nullptr; }
     958              : 
     959              :   // Creates an error state param.
     960            0 :   static MaybeNamedParam create_error ()
     961              :   {
     962            0 :     return MaybeNamedParam ({""}, UNNAMED, nullptr, {}, UNDEF_LOCATION);
     963              :   }
     964              : 
     965           46 :   location_t get_locus () const { return locus; }
     966              : 
     967              :   // TODO: this mutable getter seems really dodgy. Think up better way.
     968          948 :   std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     969              :   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     970              : 
     971              :   // TODO: would a "vis_type" be better?
     972          946 :   Type &get_type ()
     973              :   {
     974          946 :     rust_assert (param_type != nullptr);
     975          946 :     return *param_type;
     976              :   }
     977              : 
     978          146 :   std::unique_ptr<Type> &get_type_ptr ()
     979              :   {
     980          146 :     rust_assert (param_type != nullptr);
     981          146 :     return param_type;
     982              :   }
     983              : 
     984           46 :   ParamKind get_param_kind () const { return param_kind; }
     985              : 
     986           46 :   Identifier get_name () const { return name; }
     987              : };
     988              : 
     989              : /* A function pointer type - can be created via coercion from function items and
     990              :  * non-capturing closures. */
     991              : class BareFunctionType : public TypeNoBounds
     992              : {
     993              :   // bool has_for_lifetimes;
     994              :   // ForLifetimes for_lifetimes;
     995              :   std::vector<LifetimeParam> for_lifetimes; // inlined version
     996              : 
     997              :   FunctionQualifiers function_qualifiers;
     998              :   std::vector<MaybeNamedParam> params;
     999              :   bool _is_variadic;
    1000              :   std::vector<Attribute> variadic_attrs;
    1001              : 
    1002              :   // bool has_return_type;
    1003              :   // BareFunctionReturnType return_type;
    1004              :   std::unique_ptr<TypeNoBounds> return_type; // inlined version
    1005              : 
    1006              :   location_t locus;
    1007              : 
    1008              : public:
    1009              :   // Whether a return type is defined with the function.
    1010         1377 :   bool has_return_type () const { return return_type != nullptr; }
    1011              : 
    1012              :   // Whether the function has ForLifetimes.
    1013            2 :   bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
    1014              : 
    1015          990 :   std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
    1016              : 
    1017          930 :   bool is_variadic () const { return _is_variadic; }
    1018              : 
    1019            0 :   std::vector<Attribute> &get_variadic_attr () { return variadic_attrs; };
    1020              :   const std::vector<Attribute> &get_variadic_attr () const
    1021              :   {
    1022              :     return variadic_attrs;
    1023              :   };
    1024              : 
    1025           68 :   BareFunctionType (std::vector<LifetimeParam> lifetime_params,
    1026              :                     FunctionQualifiers qualifiers,
    1027              :                     std::vector<MaybeNamedParam> named_params, bool is_variadic,
    1028              :                     std::vector<Attribute> variadic_attrs,
    1029              :                     std::unique_ptr<TypeNoBounds> type, location_t locus)
    1030          136 :     : for_lifetimes (std::move (lifetime_params)),
    1031           68 :       function_qualifiers (std::move (qualifiers)),
    1032           68 :       params (std::move (named_params)), _is_variadic (is_variadic),
    1033           68 :       variadic_attrs (std::move (variadic_attrs)),
    1034           68 :       return_type (std::move (type)), locus (locus)
    1035              :   {
    1036           68 :     if (!variadic_attrs.empty ())
    1037              :       _is_variadic = true;
    1038           68 :   }
    1039              : 
    1040              :   // Copy constructor with clone
    1041           97 :   BareFunctionType (BareFunctionType const &other)
    1042          194 :     : for_lifetimes (other.for_lifetimes),
    1043           97 :       function_qualifiers (other.function_qualifiers), params (other.params),
    1044           97 :       _is_variadic (other._is_variadic), variadic_attrs (other.variadic_attrs),
    1045          194 :       locus (other.locus)
    1046              :   {
    1047              :     // guard to prevent null dereference
    1048           97 :     if (other.return_type != nullptr)
    1049           81 :       return_type = other.return_type->clone_type_no_bounds ();
    1050           97 :   }
    1051              : 
    1052              :   // Overload assignment operator to deep copy
    1053              :   BareFunctionType &operator= (BareFunctionType const &other)
    1054              :   {
    1055              :     for_lifetimes = other.for_lifetimes;
    1056              :     function_qualifiers = other.function_qualifiers;
    1057              :     params = other.params;
    1058              :     _is_variadic = other._is_variadic;
    1059              :     variadic_attrs = other.variadic_attrs;
    1060              :     locus = other.locus;
    1061              : 
    1062              :     // guard to prevent null dereference
    1063              :     if (other.return_type != nullptr)
    1064              :       return_type = other.return_type->clone_type_no_bounds ();
    1065              :     else
    1066              :       return_type = nullptr;
    1067              : 
    1068              :     return *this;
    1069              :   }
    1070              : 
    1071              :   // move constructors
    1072              :   BareFunctionType (BareFunctionType &&other) = default;
    1073              :   BareFunctionType &operator= (BareFunctionType &&other) = default;
    1074              : 
    1075              :   std::string as_string () const override;
    1076              : 
    1077          132 :   location_t get_locus () const override final { return locus; }
    1078              : 
    1079              :   void accept_vis (ASTVisitor &vis) override;
    1080              : 
    1081              :   // TODO: this mutable getter seems kinda dodgy
    1082         1377 :   std::vector<MaybeNamedParam> &get_function_params () { return params; }
    1083              :   const std::vector<MaybeNamedParam> &get_function_params () const
    1084              :   {
    1085              :     return params;
    1086              :   }
    1087              : 
    1088              :   // TODO: would a "vis_type" be better?
    1089          967 :   TypeNoBounds &get_return_type ()
    1090              :   {
    1091          967 :     rust_assert (has_return_type ());
    1092          967 :     return *return_type;
    1093              :   }
    1094              : 
    1095           48 :   std::unique_ptr<TypeNoBounds> &get_return_type_ptr ()
    1096              :   {
    1097           48 :     rust_assert (has_return_type ());
    1098           48 :     return return_type;
    1099              :   }
    1100              : 
    1101          992 :   FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
    1102              : 
    1103            2 :   BareFunctionType *reconstruct_impl () const override
    1104              :   {
    1105            2 :     std::unique_ptr<TypeNoBounds> ret_type = nullptr;
    1106            2 :     if (return_type != nullptr)
    1107            0 :       ret_type = return_type->reconstruct ();
    1108              : 
    1109            2 :     return new BareFunctionType (
    1110            6 :       for_lifetimes, function_qualifiers, params,
    1111              :       /* FIXME: Should params be reconstruct() as well? */
    1112            2 :       _is_variadic, variadic_attrs, std::move (ret_type), locus);
    1113            2 :   }
    1114              : 
    1115              : protected:
    1116              :   /* Use covariance to implement clone function as returning this object
    1117              :    * rather than base */
    1118           97 :   BareFunctionType *clone_type_no_bounds_impl () const override
    1119              :   {
    1120           97 :     return new BareFunctionType (*this);
    1121              :   }
    1122              : 
    1123            0 :   Type::Kind get_type_kind () const override
    1124              :   {
    1125            0 :     return Type::Kind::BareFunction;
    1126              :   }
    1127              : };
    1128              : 
    1129              : // Forward decl - defined in rust-macro.h
    1130              : class MacroInvocation;
    1131              : 
    1132              : /* TODO: possible types
    1133              :  * struct type?
    1134              :  * "enum" (tagged union) type?
    1135              :  * C-like union type?
    1136              :  * function item type?
    1137              :  * closure expression types?
    1138              :  * primitive types (bool, int, float, char, str (the slice))
    1139              :  * Although supposedly TypePaths are used to reference these types
    1140              :  * (including primitives) */
    1141              : 
    1142              : /* FIXME: Incomplete spec references:
    1143              :  *  anonymous type parameters, aka "impl Trait in argument position" - impl
    1144              :  * then trait bounds abstract return types, aka "impl Trait in return
    1145              :  * position" - impl then trait bounds */
    1146              : } // namespace AST
    1147              : } // namespace Rust
    1148              : 
    1149              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.