LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.7 % 82 76
Test Date: 2026-07-11 15:47:05 Functions: 91.7 % 12 11
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_HIR_TYPE_CHECK
      20              : #define RUST_HIR_TYPE_CHECK
      21              : 
      22              : #include "rust-hir-map.h"
      23              : #include "rust-mapping-common.h"
      24              : #include "rust-tyty.h"
      25              : #include "rust-hir-impl-trait-context.h"
      26              : #include "rust-hir-trait-reference.h"
      27              : #include "rust-stacked-contexts.h"
      28              : #include "rust-autoderef.h"
      29              : #include "rust-tyty-region.h"
      30              : #include "rust-tyty-variance-analysis.h"
      31              : #include "rust-system.h"
      32              : 
      33              : namespace Rust {
      34              : namespace Resolver {
      35              : 
      36              : class TypeCheckContextItem
      37              : {
      38              : public:
      39              :   enum ItemType
      40              :   {
      41              :     ITEM,
      42              :     IMPL_ITEM,
      43              :     TRAIT_ITEM,
      44              :     ERROR
      45              :   };
      46              : 
      47              :   TypeCheckContextItem (HIR::Function *item);
      48              :   TypeCheckContextItem (HIR::ImplBlock &impl_block, HIR::Function *item);
      49              :   TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
      50              :   TypeCheckContextItem (const TypeCheckContextItem &other);
      51              : 
      52              :   TypeCheckContextItem &operator= (const TypeCheckContextItem &other);
      53              : 
      54              :   static TypeCheckContextItem get_error ();
      55              : 
      56              :   bool is_error () const;
      57              : 
      58              :   ItemType get_type () const;
      59              : 
      60              :   HIR::Function *get_item ();
      61              : 
      62              :   std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
      63              : 
      64              :   HIR::TraitItemFunc *get_trait_item ();
      65              : 
      66              :   TyTy::FnType *get_context_type ();
      67              : 
      68              :   DefId get_defid () const;
      69              : 
      70              : private:
      71              :   TypeCheckContextItem ();
      72              : 
      73              :   union Item
      74              :   {
      75              :     HIR::Function *item;
      76              :     std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
      77              :     HIR::TraitItemFunc *trait_item;
      78              : 
      79              :     Item (HIR::Function *item);
      80              :     Item (HIR::ImplBlock *impl_block, HIR::Function *item);
      81              :     Item (HIR::TraitItemFunc *trait_item);
      82              :   };
      83              : 
      84              :   ItemType type;
      85              :   Item item;
      86              : };
      87              : 
      88              : class TypeCheckBlockContextItem
      89              : {
      90              : public:
      91              :   enum ItemType
      92              :   {
      93              :     IMPL_BLOCK,
      94              :     TRAIT
      95              :   };
      96              : 
      97              :   TypeCheckBlockContextItem (HIR::ImplBlock *block);
      98              :   TypeCheckBlockContextItem (HIR::Trait *trait);
      99              : 
     100              :   bool is_impl_block () const;
     101              :   bool is_trait_block () const;
     102              : 
     103              :   HIR::ImplBlock &get_impl_block ();
     104              :   HIR::Trait &get_trait ();
     105              : 
     106              : private:
     107              :   union Item
     108              :   {
     109              :     HIR::ImplBlock *block;
     110              :     HIR::Trait *trait;
     111              : 
     112              :     Item (HIR::ImplBlock *block);
     113              :     Item (HIR::Trait *trait);
     114              :   };
     115              :   ItemType type;
     116              :   Item item;
     117              : };
     118              : 
     119              : /**
     120              :  * Interned lifetime representation in TyTy
     121              :  *
     122              :  * On the HIR->TyTy boundary HIR::Lifetime is interned into this struct.
     123              :  */
     124              : class Lifetime
     125              : {
     126              :   uint32_t interner_index;
     127              : 
     128              : public:
     129           97 :   explicit constexpr Lifetime (uint32_t interner_index)
     130              :     : interner_index (interner_index)
     131              :   {}
     132              : 
     133              :   Lifetime () = default;
     134              : 
     135        29721 :   WARN_UNUSED_RESULT bool is_static () const { return interner_index == 0; }
     136              : 
     137              :   WARN_UNUSED_RESULT static constexpr Lifetime static_lifetime ()
     138              :   {
     139              :     return Lifetime (0);
     140              :   }
     141              : 
     142              :   WARN_UNUSED_RESULT static constexpr Lifetime anonymous_lifetime ()
     143              :   {
     144              :     return Lifetime (1);
     145              :   }
     146              : 
     147              :   static constexpr uint32_t FIRST_NAMED_LIFETIME = 2;
     148              : 
     149          314 :   friend bool operator== (const Lifetime &lhs, const Lifetime &rhs)
     150              :   {
     151          314 :     return lhs.interner_index == rhs.interner_index;
     152              :   }
     153              : 
     154              :   friend bool operator!= (const Lifetime &lhs, const Lifetime &rhs)
     155              :   {
     156              :     return !(lhs == rhs);
     157              :   }
     158              : 
     159           97 :   WARN_UNUSED_RESULT Lifetime next () { return Lifetime (interner_index++); }
     160              : };
     161              : 
     162           24 : struct DeferredOpOverload
     163              : {
     164              :   HirId expr_id;
     165              :   LangItem::Kind lang_item_type;
     166              :   HIR::PathIdentSegment specified_segment;
     167              :   TyTy::TypeBoundPredicate predicate;
     168              :   HIR::OperatorExprMeta op;
     169              : 
     170            8 :   DeferredOpOverload (HirId expr_id, LangItem::Kind lang_item_type,
     171              :                       HIR::PathIdentSegment specified_segment,
     172              :                       TyTy::TypeBoundPredicate &predicate,
     173              :                       HIR::OperatorExprMeta op)
     174            8 :     : expr_id (expr_id), lang_item_type (lang_item_type),
     175           16 :       specified_segment (specified_segment), predicate (predicate), op (op)
     176            8 :   {}
     177              : 
     178           24 :   DeferredOpOverload (const struct DeferredOpOverload &other)
     179           24 :     : expr_id (other.expr_id), lang_item_type (other.lang_item_type),
     180           48 :       specified_segment (other.specified_segment), predicate (other.predicate),
     181           24 :       op (other.op)
     182           24 :   {}
     183              : 
     184            0 :   DeferredOpOverload &operator= (struct DeferredOpOverload const &other)
     185              :   {
     186            0 :     expr_id = other.expr_id;
     187            0 :     lang_item_type = other.lang_item_type;
     188            0 :     specified_segment = other.specified_segment;
     189            0 :     op = other.op;
     190              : 
     191            0 :     return *this;
     192              :   }
     193              : };
     194              : 
     195              : class TypeCheckContext
     196              : {
     197              : public:
     198              :   static TypeCheckContext *get ();
     199              : 
     200              :   ~TypeCheckContext ();
     201              : 
     202              :   bool lookup_builtin (NodeId id, TyTy::BaseType **type);
     203              :   bool lookup_builtin (std::string name, TyTy::BaseType **type);
     204              :   void insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type);
     205              :   const std::vector<std::unique_ptr<TyTy::BaseType>> &get_builtins () const;
     206              : 
     207              :   void insert_type (const Analysis::NodeMapping &mappings,
     208              :                     TyTy::BaseType *type);
     209              :   bool lookup_type (HirId id, TyTy::BaseType **type) const;
     210              :   void clear_type (TyTy::BaseType *ty);
     211              : 
     212              :   void insert_implicit_type (HirId id, TyTy::BaseType *type);
     213              : 
     214              :   void insert_type_by_node_id (NodeId ref, HirId id);
     215              :   bool lookup_type_by_node_id (NodeId ref, HirId *id);
     216              : 
     217              :   bool have_function_context () const;
     218              :   TyTy::BaseType *peek_return_type ();
     219              :   TypeCheckContextItem peek_context ();
     220              :   void push_return_type (TypeCheckContextItem item,
     221              :                          TyTy::BaseType *return_type);
     222              :   void pop_return_type ();
     223              : 
     224              :   void push_expected_type (TyTy::BaseType *expected);
     225              :   void pop_expected_type ();
     226              :   TyTy::BaseType *peek_expected_type () const;
     227              : 
     228              :   StackedContexts<TypeCheckBlockContextItem> &block_context ();
     229              : 
     230              :   void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
     231              : 
     232              :   bool have_loop_context () const;
     233              :   void push_new_loop_context (HirId id, location_t locus);
     234              :   void push_new_while_loop_context (HirId id);
     235              :   TyTy::BaseType *peek_loop_context ();
     236              :   TyTy::BaseType *pop_loop_context ();
     237              : 
     238              :   void swap_head_loop_context (TyTy::BaseType *val);
     239              : 
     240              :   bool
     241              :   find_matching_impl_trait_frame (const TraitReference &tref,
     242              :                                   struct ImplTraitContextFrame *find) const;
     243              :   bool have_impl_trait_context () const;
     244              :   void push_impl_trait_context (struct ImplTraitContextFrame frame);
     245              :   struct ImplTraitContextFrame pop_impl_trait_context ();
     246              :   struct ImplTraitContextFrame peek_impl_trait_context ();
     247              : 
     248              :   void insert_trait_reference (DefId id, TraitReference &&ref);
     249              :   bool lookup_trait_reference (DefId id, TraitReference **ref);
     250              : 
     251              :   bool insert_associated_trait_impl (HirId id,
     252              :                                      AssociatedImplTrait &&associated);
     253              :   bool lookup_associated_trait_impl (HirId id,
     254              :                                      AssociatedImplTrait **associated);
     255              : 
     256              :   void insert_associated_type_mapping (HirId id, HirId mapping);
     257              :   void clear_associated_type_mapping (HirId id);
     258              : 
     259              :   // lookup any associated type mappings, the out parameter of mapping is
     260              :   // allowed to be nullptr which allows this interface to do a simple does exist
     261              :   // check
     262              :   bool lookup_associated_type_mapping (HirId id, HirId *mapping);
     263              : 
     264              :   void insert_associated_impl_mapping (HirId trait_id,
     265              :                                        TyTy::BaseType *impl_type,
     266              :                                        HirId impl_id);
     267              :   bool lookup_associated_impl_mapping_for_self (HirId trait_id,
     268              :                                                 TyTy::BaseType *self,
     269              :                                                 HirId *mapping);
     270              : 
     271              :   void insert_autoderef_mappings (HirId id,
     272              :                                   std::vector<Adjustment> &&adjustments);
     273              :   bool lookup_autoderef_mappings (HirId id,
     274              :                                   std::vector<Adjustment> **adjustments);
     275              : 
     276              :   void insert_cast_autoderef_mappings (HirId id,
     277              :                                        std::vector<Adjustment> &&adjustments);
     278              :   bool lookup_cast_autoderef_mappings (HirId id,
     279              :                                        std::vector<Adjustment> **adjustments);
     280              : 
     281              :   void insert_variant_definition (HirId id, HirId variant);
     282              :   bool lookup_variant_definition (HirId id, HirId *variant);
     283              : 
     284              :   void insert_operator_overload (HirId id, TyTy::FnType *call_site);
     285              :   bool lookup_operator_overload (HirId id, TyTy::FnType **call);
     286              : 
     287              :   void insert_deferred_operator_overload (DeferredOpOverload deferred);
     288              :   bool lookup_deferred_operator_overload (HirId id,
     289              :                                           DeferredOpOverload *deferred);
     290              : 
     291              :   void iterate_deferred_operator_overloads (
     292              :     std::function<bool (HirId, DeferredOpOverload &)> cb);
     293              : 
     294              :   void insert_unconstrained_check_marker (HirId id, bool status);
     295              :   bool have_checked_for_unconstrained (HirId id, bool *result);
     296              : 
     297              :   void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
     298              :   bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
     299              : 
     300              :   void insert_query (HirId id);
     301              :   void query_completed (HirId id);
     302              :   bool query_in_progress (HirId id) const;
     303              : 
     304              :   void insert_trait_query (DefId id);
     305              :   void trait_query_completed (DefId id);
     306              :   bool trait_query_in_progress (DefId id) const;
     307              : 
     308              :   Lifetime intern_lifetime (const HIR::Lifetime &name);
     309              :   WARN_UNUSED_RESULT tl::optional<Lifetime>
     310              :   lookup_lifetime (const HIR::Lifetime &lifetime) const;
     311              : 
     312              :   WARN_UNUSED_RESULT tl::optional<TyTy::Region>
     313              :   lookup_and_resolve_lifetime (const HIR::Lifetime &lifetime) const;
     314              : 
     315              :   void intern_and_insert_lifetime (const HIR::Lifetime &lifetime);
     316              : 
     317              :   WARN_UNUSED_RESULT std::vector<TyTy::Region>
     318              :   regions_from_generic_args (const HIR::GenericArgs &args) const;
     319              : 
     320              :   void compute_inference_variables (bool emit_error);
     321              : 
     322              :   TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx ();
     323              : 
     324              : private:
     325              :   TypeCheckContext ();
     326              : 
     327              :   bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error);
     328              :   bool compute_ambigious_op_overload (HirId id, DeferredOpOverload &op);
     329              : 
     330              :   std::map<NodeId, HirId> node_id_refs;
     331              :   std::map<HirId, TyTy::BaseType *> resolved;
     332              :   std::vector<std::unique_ptr<TyTy::BaseType>> builtins;
     333              :   std::vector<std::pair<TypeCheckContextItem, TyTy::BaseType *>>
     334              :     return_type_stack;
     335              :   std::vector<TyTy::BaseType *> expected_type_stack;
     336              :   std::vector<TyTy::BaseType *> loop_type_stack;
     337              :   StackedContexts<TypeCheckBlockContextItem> block_stack;
     338              :   std::map<DefId, TraitReference> trait_context;
     339              :   std::map<HirId, AssociatedImplTrait> associated_impl_traits;
     340              :   std::vector<ImplTraitContextFrame> impl_trait_frame_stack;
     341              : 
     342              :   // trait-id -> list of < self-tyty:impl-id>
     343              :   std::map<HirId, std::vector<std::pair<TyTy::BaseType *, HirId>>>
     344              :     associated_traits_to_impls;
     345              : 
     346              :   std::map<HirId, HirId> associated_type_mappings;
     347              : 
     348              :   // adjustment mappings
     349              :   std::map<HirId, std::vector<Adjustment>> autoderef_mappings;
     350              :   std::map<HirId, std::vector<Adjustment>> cast_autoderef_mappings;
     351              : 
     352              :   // operator overloads
     353              :   std::map<HirId, TyTy::FnType *> operator_overloads;
     354              : 
     355              :   // variants
     356              :   std::map<HirId, HirId> variants;
     357              : 
     358              :   // unconstrained type-params check
     359              :   std::map<HirId, bool> unconstrained;
     360              : 
     361              :   // predicates
     362              :   std::map<HirId, TyTy::TypeBoundPredicate> predicates;
     363              : 
     364              :   // query context lookups
     365              :   std::set<HirId> querys_in_progress;
     366              :   std::set<DefId> trait_queries_in_progress;
     367              : 
     368              :   // deferred operator overload
     369              :   std::map<HirId, DeferredOpOverload> deferred_operator_overloads;
     370              : 
     371              :   // variance analysis
     372              :   TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx;
     373              : 
     374              :   /** Used to resolve (interned) lifetime names to their bounding scope. */
     375       140924 :   class LifetimeResolver
     376              :   {
     377              :     /**
     378              :      * The level of nested scopes, where the lifetime was declared.
     379              :      *
     380              :      * Index 0 is used for `impl` blocks and is skipped if not explicitly
     381              :      * requested.
     382              :      * Index 1 for the top-level of declarations of items.
     383              :      * Index >1 is used for late-bound lifetimes.
     384              :      */
     385              :     using ScopeIndex = size_t;
     386              : 
     387              :     static constexpr ScopeIndex IMPL_SCOPE = 0;
     388              :     static constexpr ScopeIndex ITEM_SCOPE = 1;
     389              : 
     390              :     /**
     391              :      * A reference to a lifetime binder.
     392              :      *
     393              :      * This is used to resolve lifetimes to their scope.
     394              :      */
     395              :     struct LifetimeBinderRef
     396              :     {
     397              :       uint32_t scope; //> Depth of the scope where the lifetime was declared.
     398              :       uint32_t index; //> Index of the lifetime in the scope.
     399              :     };
     400              : 
     401              :     /**
     402              :      * A stack of the number of lifetimes declared in each scope.
     403              :      *
     404              :      * Used to pop the correct number of lifetimes when leaving a scope.
     405              :      */
     406              :     std::stack<uint32_t> binder_size_stack;
     407              : 
     408              :     /**
     409              :      * Merged stack of all lifetimes declared in all scopes.
     410              :      *
     411              :      * Use `binder_size_stack` to determine the number of lifetimes in each
     412              :      * scope.
     413              :      */
     414              :     std::vector<std::pair<Lifetime, LifetimeBinderRef>> lifetime_lookup;
     415              : 
     416              :     /**
     417              :      * Whether the current scope is a function body.
     418              :      *
     419              :      * In function header, lifetimes are resolved as early-bound, in the body as
     420              :      * named. This is because the header can be also used in call position.
     421              :      */
     422              :     bool is_body = false;
     423              : 
     424              :     /** Return the number of the current scope. */
     425         1034 :     WARN_UNUSED_RESULT uint32_t get_current_scope () const
     426              :     {
     427         2001 :       return binder_size_stack.size () - 1;
     428              :     }
     429              : 
     430              :   public:
     431              :     /** Add new declaration of a lifetime. */
     432          967 :     void insert_mapping (Lifetime placeholder)
     433              :     {
     434          967 :       lifetime_lookup.push_back (
     435          967 :         {placeholder, {get_current_scope (), binder_size_stack.top ()++}});
     436          967 :     }
     437              : 
     438              :     WARN_UNUSED_RESULT tl::optional<TyTy::Region>
     439              :     resolve (const Lifetime &placeholder) const;
     440              : 
     441              :     /** Only to be used by the guard. */
     442       100316 :     void push_binder () { binder_size_stack.push (0); }
     443              :     /** Only to be used by the guard. */
     444        58717 :     void pop_binder () { binder_size_stack.pop (); }
     445              : 
     446        58725 :     bool binder_empty () { return binder_size_stack.empty (); }
     447              : 
     448              :     /**
     449              :      * Switch from resolving a function header to a function body.
     450              :      */
     451         6577 :     void switch_to_fn_body () { this->is_body = true; }
     452              : 
     453        43551 :     size_t get_num_bound_regions () const { return binder_size_stack.top (); }
     454              :   };
     455              : 
     456              :   // lifetime resolving
     457              :   std::unordered_map<std::string, Lifetime> lifetime_name_interner;
     458              :   Lifetime next_lifetime_index = Lifetime (Lifetime::FIRST_NAMED_LIFETIME);
     459              : 
     460              :   /**
     461              :    * Stack of lifetime resolvers.
     462              :    *
     463              :    * Due to the contruction of the type checker, it is possible to start
     464              :    * resolution of a new type in the middle of resolving another type. This
     465              :    * stack isolates the conexts in such cases.
     466              :    */
     467              :   std::stack<LifetimeResolver> lifetime_resolver_stack;
     468              : 
     469              : public:
     470        44518 :   WARN_UNUSED_RESULT LifetimeResolver &get_lifetime_resolver ()
     471              :   {
     472        44518 :     rust_assert (!lifetime_resolver_stack.empty ());
     473        44518 :     return lifetime_resolver_stack.top ();
     474              :   }
     475              : 
     476        29721 :   WARN_UNUSED_RESULT const LifetimeResolver &get_lifetime_resolver () const
     477              :   {
     478        29721 :     rust_assert (!lifetime_resolver_stack.empty ());
     479        29721 :     return lifetime_resolver_stack.top ();
     480              :   }
     481              : 
     482              :   /**
     483              :    * A guard that pushes a new lifetime resolver on the stack and pops it
     484              :    * when it goes out of scope.
     485              :    */
     486              :   class LifetimeResolverGuard
     487              :   {
     488              :   public:
     489              :     /** The kind of scope that is being pushed. */
     490              :     enum ScopeKind
     491              :     {
     492              :       IMPL_BLOCK_RESOLVER, //> A new `impl` block scope.
     493              :       RESOLVER,            //> A new scope for a function body.
     494              :       BINDER,              //> A new scope for late-bound lifetimes.
     495              :     };
     496              : 
     497              :   private:
     498              :     TypeCheckContext &ctx;
     499              :     ScopeKind kind;
     500              : 
     501              :   public:
     502        58725 :     LifetimeResolverGuard (TypeCheckContext &ctx, ScopeKind kind)
     503        58725 :       : ctx (ctx), kind (kind)
     504              :     {
     505        58725 :       if (kind == IMPL_BLOCK_RESOLVER)
     506              :         {
     507        11384 :           ctx.lifetime_resolver_stack.push (LifetimeResolver ());
     508              :         }
     509              : 
     510        58725 :       if (kind == RESOLVER)
     511              :         {
     512        41591 :           ctx.lifetime_resolver_stack.push (LifetimeResolver ());
     513              :           // Skip the `impl` block scope.
     514        41591 :           ctx.lifetime_resolver_stack.top ().push_binder ();
     515              :         }
     516        58725 :       rust_assert (!ctx.lifetime_resolver_stack.empty ());
     517        58725 :       ctx.lifetime_resolver_stack.top ().push_binder ();
     518        58725 :     }
     519              : 
     520        58725 :     ~LifetimeResolverGuard ()
     521              :     {
     522        58725 :       rust_assert (!ctx.lifetime_resolver_stack.empty ());
     523        58725 :       if (!ctx.lifetime_resolver_stack.top ().binder_empty ())
     524        58717 :         ctx.lifetime_resolver_stack.top ().pop_binder ();
     525        58725 :       if (kind == RESOLVER)
     526              :         {
     527        41591 :           ctx.lifetime_resolver_stack.pop ();
     528              :         }
     529        58725 :     }
     530              :   };
     531              : 
     532              :   /** Start new late bound lifetime scope. */
     533        11442 :   WARN_UNUSED_RESULT LifetimeResolverGuard push_lifetime_binder ()
     534              :   {
     535        11442 :     return LifetimeResolverGuard (*this, LifetimeResolverGuard::BINDER);
     536              :   }
     537              : 
     538              :   /** Start new function body scope. */
     539              :   WARN_UNUSED_RESULT LifetimeResolverGuard
     540        47283 :   push_clean_lifetime_resolver (bool is_impl_block = false)
     541              :   {
     542        47283 :     return LifetimeResolverGuard (*this,
     543              :                                   is_impl_block
     544              :                                     ? LifetimeResolverGuard::IMPL_BLOCK_RESOLVER
     545        47283 :                                     : LifetimeResolverGuard::RESOLVER);
     546              :   }
     547              : 
     548              :   /** Switch from resolving a function header to a function body. */
     549         6577 :   void switch_to_fn_body ()
     550              :   {
     551         6577 :     this->lifetime_resolver_stack.top ().switch_to_fn_body ();
     552              :   }
     553              : };
     554              : 
     555              : class TypeResolution
     556              : {
     557              : public:
     558              :   static void Resolve (HIR::Crate &crate);
     559              : };
     560              : 
     561              : class TraitQueryGuard
     562              : {
     563              : public:
     564         3934 :   TraitQueryGuard (DefId id) : id (id), ctx (*TypeCheckContext::get ())
     565              :   {
     566         3934 :     ctx.insert_trait_query (id);
     567         3934 :   }
     568              : 
     569         3934 :   ~TraitQueryGuard () { ctx.trait_query_completed (id); }
     570              : 
     571              : private:
     572              :   DefId id;
     573              :   TypeCheckContext &ctx;
     574              : };
     575              : 
     576              : template <typename T> class ScopedPush
     577              : {
     578              : public:
     579      1599067 :   ScopedPush (std::vector<T> &stack, T value, bool enabled = true)
     580      1599067 :     : stack (stack), enabled (enabled)
     581              :   {
     582        51002 :     if (enabled)
     583      1599037 :       stack.push_back (value);
     584              :   }
     585              : 
     586      1599067 :   ~ScopedPush ()
     587              :   {
     588        51002 :     if (enabled)
     589      1599037 :       stack.pop_back ();
     590      1599067 :   }
     591              : 
     592      1599137 :   static bool contains (const std::vector<T> &stack, const T &value)
     593              :   {
     594      3147230 :     return std::find (stack.begin (), stack.end (), value) != stack.end ();
     595              :   }
     596              : 
     597              : private:
     598              :   std::vector<T> &stack;
     599              :   bool enabled;
     600              : };
     601              : 
     602              : class ImplTraitFrameGuard
     603              : {
     604              : public:
     605        13326 :   ImplTraitFrameGuard (ImplTraitContextFrame frame)
     606        13326 :     : ctx (*TypeCheckContext::get ())
     607              :   {
     608        13326 :     ctx.push_impl_trait_context (frame);
     609        13326 :   }
     610              : 
     611        13326 :   ~ImplTraitFrameGuard () { ctx.pop_impl_trait_context (); }
     612              : 
     613              : private:
     614              :   Resolver::TypeCheckContext &ctx;
     615              : };
     616              : 
     617              : } // namespace Resolver
     618              : } // namespace Rust
     619              : 
     620              : #endif // RUST_HIR_TYPE_CHECK
        

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.