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