LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-resolve-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.8 % 192 182
Test Date: 2026-10-17 16:30:31 Functions: 100.0 % 9 9
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              : #include "rust-compile-resolve-path.h"
      20              : #include "options.h"
      21              : #include "rust-compile-intrinsic.h"
      22              : #include "rust-compile-item.h"
      23              : #include "rust-compile-implitem.h"
      24              : #include "rust-compile-expr.h"
      25              : #include "rust-hir-map.h"
      26              : #include "rust-hir-trait-resolve.h"
      27              : #include "rust-hir-path-probe-impl-trait.h"
      28              : #include "rust-compile-extern.h"
      29              : #include "rust-constexpr.h"
      30              : #include "rust-rib.h"
      31              : #include "rust-tyty.h"
      32              : 
      33              : namespace Rust {
      34              : namespace Compile {
      35              : 
      36              : tree
      37          121 : ResolvePathRef::Compile (HIR::QualifiedPathInExpression &expr, Context *ctx)
      38              : {
      39          121 :   ResolvePathRef resolver (ctx);
      40          121 :   return resolver.resolve_path_like (expr);
      41          121 : }
      42              : 
      43              : tree
      44        46822 : ResolvePathRef::Compile (HIR::PathInExpression &expr, Context *ctx)
      45              : {
      46        46822 :   ResolvePathRef resolver (ctx);
      47        46822 :   return resolver.resolve_path_like (expr);
      48        46822 : }
      49              : 
      50        46943 : ResolvePathRef::ResolvePathRef (Context *ctx) : HIRCompileBase (ctx) {}
      51              : 
      52              : template <typename T>
      53              : tree
      54        46943 : ResolvePathRef::resolve_path_like (T &expr)
      55              : {
      56        46943 :   if (expr.is_lang_item ())
      57              :     {
      58              :       auto lang_item
      59           55 :         = Analysis::Mappings::get ().get_lang_item_node (expr.get_lang_item ());
      60              : 
      61              :       // FIXME: Is that correct? :/
      62           55 :       auto final_segment
      63          110 :         = HIR::PathIdentSegment (LangItem::ToString (expr.get_lang_item ()));
      64              : 
      65           55 :       return resolve_with_node_id (final_segment, expr.get_mappings (),
      66              :                                    expr.get_locus (), true, lang_item);
      67           55 :     }
      68              : 
      69        46888 :   return resolve (expr.get_final_segment ().get_segment (),
      70        46888 :                   expr.get_mappings (), expr.get_locus (), true);
      71              : }
      72              : 
      73              : tree
      74         1398 : ResolvePathRef::attempt_constructor_expression_lookup (
      75              :   TyTy::BaseType *lookup, Context *ctx, const Analysis::NodeMapping &mappings,
      76              :   location_t expr_locus)
      77              : {
      78              :   // it might be an enum data-less enum variant
      79         1398 :   if (lookup->get_kind () != TyTy::TypeKind::ADT)
      80            2 :     return error_mark_node;
      81              : 
      82         1396 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
      83         1396 :   if (adt->is_unit ())
      84              :     {
      85          228 :       tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
      86          228 :       return Backend::constructor_expression (compiled_adt_type, false, {}, -1,
      87              :                                               expr_locus);
      88              :     }
      89              : 
      90         1168 :   if (!adt->is_enum ())
      91            3 :     return error_mark_node;
      92              : 
      93         1165 :   HirId variant_id;
      94         1165 :   if (!ctx->get_tyctx ()->lookup_variant_definition (mappings.get_hirid (),
      95              :                                                      &variant_id))
      96            0 :     return error_mark_node;
      97              : 
      98         1165 :   int union_disriminator = -1;
      99         1165 :   TyTy::VariantDef *variant = nullptr;
     100         1165 :   if (!adt->lookup_variant_by_id (variant_id, &variant, &union_disriminator))
     101            0 :     return error_mark_node;
     102              : 
     103              :   // this can only be for discriminant variants the others are built up
     104              :   // using call-expr or struct-init
     105         1165 :   if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
     106              :     {
     107            1 :       rust_error_at (expr_locus, "variant expected constructor call");
     108            1 :       return error_mark_node;
     109              :     }
     110              : 
     111              :   // we need the actual gcc type
     112         1164 :   tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
     113              : 
     114              :   // make the ctor for the union
     115         1164 :   HIR::Expr &discrim_expr = variant->get_discriminant ();
     116         1164 :   ctx->push_const_context ();
     117         1164 :   tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
     118         1164 :   ctx->pop_const_context ();
     119         1164 :   tree folded_discrim_expr = fold_expr (discrim_expr_node);
     120         1164 :   tree qualifier = folded_discrim_expr;
     121              : 
     122              :   // false for is enum but this is an enum but we have a new layout
     123         1164 :   return Backend::constructor_expression (compiled_adt_type, false, {qualifier},
     124              :                                           -1, expr_locus);
     125              : }
     126              : 
     127              : tree
     128        46941 : ResolvePathRef::resolve_with_node_id (
     129              :   const HIR::PathIdentSegment &final_segment,
     130              :   const Analysis::NodeMapping &mappings, location_t expr_locus,
     131              :   bool is_qualified_path, NodeId resolved_node_id)
     132              : {
     133        46941 :   TyTy::BaseType *lookup = nullptr;
     134        46941 :   bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
     135        46941 :   rust_assert (ok);
     136              : 
     137        46941 :   tl::optional<HirId> hid
     138        46941 :     = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id);
     139        46941 :   if (!hid.has_value ())
     140            0 :     return error_mark_node;
     141              : 
     142        46941 :   auto ref = hid.value ();
     143              : 
     144              :   // might be a constant
     145        46941 :   tree constant_expr;
     146        46941 :   if (ctx->lookup_const_decl (ref, &constant_expr))
     147              :     {
     148          588 :       TREE_USED (constant_expr) = 1;
     149          588 :       return constant_expr;
     150              :     }
     151              : 
     152              :   // maybe closure binding
     153        46353 :   tree closure_binding = error_mark_node;
     154        46353 :   if (ctx->lookup_closure_binding (ref, &closure_binding))
     155              :     {
     156           14 :       TREE_USED (closure_binding) = 1;
     157           14 :       return closure_binding;
     158              :     }
     159              : 
     160              :   // this might be a variable reference or a function reference
     161        46339 :   Bvariable *var = nullptr;
     162        46339 :   if (ctx->lookup_var_decl (ref, &var))
     163              :     {
     164              :       // TREE_USED is setup in the gcc abstraction here
     165        32498 :       return Backend::var_expression (var, expr_locus);
     166              :     }
     167              : 
     168              :   // might be a match pattern binding
     169        13841 :   tree binding = error_mark_node;
     170        13841 :   if (ctx->lookup_pattern_binding (ref, &binding))
     171              :     {
     172          877 :       TREE_USED (binding) = 1;
     173          877 :       return binding;
     174              :     }
     175              : 
     176              :   // it might be a function call
     177        12964 :   if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
     178              :     {
     179        11414 :       TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
     180        11414 :       tree fn = NULL_TREE;
     181        11414 :       if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
     182              :         {
     183         5871 :           TREE_USED (fn) = 1;
     184         9202 :           return address_expression (fn, expr_locus);
     185              :         }
     186         5543 :       else if (fntype->get_abi () == ABI::INTRINSIC)
     187              :         {
     188         3331 :           Intrinsics compile (ctx);
     189         3331 :           fn = compile.compile (fntype, expr_locus);
     190         3331 :           TREE_USED (fn) = 1;
     191         3331 :           return address_expression (fn, expr_locus);
     192              :         }
     193              :     }
     194              : 
     195              :   // possibly a const expr value
     196         3762 :   if (lookup->get_kind () == TyTy::TypeKind::CONST)
     197              :     {
     198           37 :       auto d = lookup->destructure ();
     199           37 :       rust_assert (d->get_kind () == TyTy::TypeKind::CONST);
     200           37 :       auto c = d->as_const_type ();
     201           37 :       if (c->const_kind () != TyTy::BaseConstType::ConstKind::Value)
     202            1 :         return error_mark_node;
     203              : 
     204           36 :       auto val = static_cast<TyTy::ConstValueType *> (c);
     205           36 :       return val->get_value ();
     206              :     }
     207              : 
     208              :   // Handle unit struct
     209         3725 :   tree resolved_item = error_mark_node;
     210         3725 :   if (lookup->get_kind () == TyTy::TypeKind::ADT)
     211         1396 :     resolved_item
     212         1396 :       = attempt_constructor_expression_lookup (lookup, ctx, mappings,
     213              :                                                expr_locus);
     214              : 
     215         3725 :   if (!error_operand_p (resolved_item))
     216              :     return resolved_item;
     217              : 
     218              :   // let the query system figure it out
     219         2334 :   resolved_item = query_compile (ref, lookup, final_segment, mappings,
     220              :                                  expr_locus, is_qualified_path);
     221         2334 :   if (resolved_item != error_mark_node)
     222         2328 :     TREE_USED (resolved_item) = 1;
     223              : 
     224              :   return resolved_item;
     225              : }
     226              : 
     227              : tree
     228        46888 : ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
     229              :                          const Analysis::NodeMapping &mappings,
     230              :                          location_t expr_locus, bool is_qualified_path)
     231              : {
     232        46888 :   TyTy::BaseType *lookup = nullptr;
     233        46888 :   bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
     234        46888 :   if (!ok)
     235            0 :     return error_mark_node;
     236              : 
     237              :   // need to look up the reference for this identifier
     238              : 
     239              :   // this can fail because it might be a Constructor for something
     240              :   // in that case the caller should attempt ResolvePathType::Compile
     241        46888 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     242              : 
     243              :   // TODO: Is Values the correct NS here?
     244        46888 :   auto resolved
     245        46888 :     = nr_ctx.lookup (mappings.get_nodeid (), Resolver2_0::Namespace::Values);
     246              : 
     247        46888 :   if (!resolved)
     248            2 :     return attempt_constructor_expression_lookup (lookup, ctx, mappings,
     249            2 :                                                   expr_locus);
     250              : 
     251        46886 :   return resolve_with_node_id (final_segment, mappings, expr_locus,
     252        93772 :                                is_qualified_path, *resolved);
     253              : }
     254              : 
     255              : tree
     256         2334 : HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
     257              :                                const HIR::PathIdentSegment &final_segment,
     258              :                                const Analysis::NodeMapping &mappings,
     259              :                                location_t expr_locus, bool is_qualified_path)
     260              : {
     261         2334 :   bool is_fn = lookup->get_kind () == TyTy::TypeKind::FNDEF;
     262         2334 :   if (auto resolved_item = ctx->get_mappings ().hir.items.lookup (ref))
     263              :     {
     264         1012 :       if (!lookup->has_substitutions_defined ())
     265         2332 :         return CompileItem::compile (*resolved_item, ctx, nullptr, expr_locus);
     266              :       else
     267          785 :         return CompileItem::compile (*resolved_item, ctx, lookup, expr_locus);
     268              :     }
     269         1322 :   else if (auto hir_extern_item
     270         1322 :            = ctx->get_mappings ().lookup_hir_extern_item (ref))
     271              :     {
     272           30 :       HIR::ExternalItem *resolved_extern_item = hir_extern_item->first;
     273           30 :       if (!lookup->has_substitutions_defined ())
     274           30 :         return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
     275         1320 :                                            expr_locus);
     276              :       else
     277            0 :         return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
     278            0 :                                            expr_locus);
     279              :     }
     280              :   else
     281              :     {
     282         1292 :       if (is_fn)
     283              :         {
     284         1288 :           TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
     285         1288 :           TyTy::BaseType *receiver = nullptr;
     286              : 
     287         2421 :           if (fn->is_method ())
     288              :             {
     289          419 :               receiver = fn->get_self_type ();
     290          419 :               receiver = receiver->destructure ();
     291              : 
     292          419 :               return resolve_method_address (fn, receiver, expr_locus);
     293              :             }
     294              :         }
     295              : 
     296          873 :       if (auto resolved_item = ctx->get_mappings ().lookup_hir_implitem (ref))
     297              :         {
     298          618 :           if (!lookup->has_substitutions_defined ())
     299          384 :             return CompileInherentImplItem::Compile (resolved_item->first, ctx,
     300          871 :                                                      nullptr, expr_locus);
     301              :           else
     302          234 :             return CompileInherentImplItem::Compile (resolved_item->first, ctx,
     303          234 :                                                      lookup, expr_locus);
     304              :         }
     305          255 :       else if (auto trait_item
     306          255 :                = ctx->get_mappings ().hir.trait_items.lookup (ref))
     307              :         {
     308          253 :           HIR::Trait *trait = ctx->get_mappings ().lookup_trait_item_mapping (
     309          253 :             trait_item.value ()->get_mappings ().get_hirid ());
     310              : 
     311          253 :           Resolver::TraitReference *trait_ref
     312          253 :             = &Resolver::TraitReference::error_node ();
     313          253 :           bool ok = ctx->get_tyctx ()->lookup_trait_reference (
     314          253 :             trait->get_mappings ().get_defid (), &trait_ref);
     315          253 :           rust_assert (ok);
     316              : 
     317          253 :           if (trait_item.value ()->get_item_kind ()
     318              :               == HIR::TraitItem::TraitItemKind::CONST)
     319              :             {
     320            2 :               auto &c
     321            2 :                 = *static_cast<HIR::TraitItemConst *> (trait_item.value ());
     322            2 :               if (!c.has_expr ())
     323              :                 {
     324            2 :                   rich_location r (line_table, expr_locus);
     325            2 :                   r.add_range (trait->get_locus ());
     326            2 :                   r.add_range (c.get_locus ());
     327            2 :                   rust_error_at (r, "no default expression on trait constant");
     328            2 :                   return error_mark_node;
     329            2 :                 }
     330              : 
     331            0 :               return CompileExpr::Compile (c.get_expr (), ctx);
     332              :             }
     333              : 
     334          251 :           if (trait_item.value ()->get_item_kind ()
     335              :               != HIR::TraitItem::TraitItemKind::FUNC)
     336            0 :             return error_mark_node;
     337              : 
     338              :           // the type resolver can only resolve type bounds to their trait
     339              :           // item so its up to us to figure out if this path should resolve
     340              :           // to an trait-impl-block-item or if it can be defaulted to the
     341              :           // trait-impl-item's definition
     342              :           //
     343              :           // because we know this is resolved to a trait item we can actually
     344              :           // just grab the Self type parameter here for the receiver to match
     345              :           // the appropriate impl block
     346              : 
     347          251 :           rust_assert (lookup->is<TyTy::FnType> ());
     348          251 :           auto fn = lookup->as<TyTy::FnType> ();
     349          251 :           rust_assert (fn->get_num_type_params () > 0);
     350          251 :           TyTy::SubstitutionParamMapping &self = fn->get_substs ().at (0);
     351          251 :           TyTy::BaseGeneric *receiver = self.get_param_ty ();
     352          251 :           TyTy::BaseType *r = receiver;
     353          251 :           if (!receiver->can_resolve ())
     354              :             {
     355          117 :               bool ok
     356          117 :                 = ctx->get_tyctx ()->lookup_type (receiver->get_ref (), &r);
     357          117 :               rust_assert (ok);
     358              :             }
     359              : 
     360          251 :           auto candidates
     361          251 :             = Resolver::PathProbeImplTrait::Probe (r, final_segment, trait_ref);
     362          251 :           if (candidates.size () == 0)
     363              :             {
     364              :               // this means we are defaulting back to the trait_item if
     365              :               // possible
     366          110 :               Resolver::TraitItemReference *trait_item_ref = nullptr;
     367          110 :               bool ok = trait_ref->lookup_hir_trait_item (*trait_item.value (),
     368              :                                                           &trait_item_ref);
     369          110 :               rust_assert (ok);                             // found
     370          110 :               rust_assert (trait_item_ref->is_optional ()); // has definition
     371              : 
     372          110 :               return CompileTraitItem::Compile (
     373              :                 trait_item_ref->get_hir_trait_item (), ctx, lookup, true,
     374              :                 expr_locus);
     375              :             }
     376              :           else
     377              :             {
     378          141 :               rust_assert (candidates.size () == 1);
     379              : 
     380          141 :               auto candidate = *candidates.begin ();
     381          141 :               rust_assert (candidate.is_impl_candidate ());
     382              : 
     383          141 :               HIR::ImplBlock *impl = candidate.item.impl.parent;
     384          141 :               HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
     385              : 
     386          141 :               TyTy::BaseType *self = nullptr;
     387          282 :               bool ok = ctx->get_tyctx ()->lookup_type (
     388          141 :                 impl->get_type ().get_mappings ().get_hirid (), &self);
     389          141 :               rust_assert (ok);
     390              : 
     391          141 :               if (!lookup->has_substitutions_defined ())
     392            0 :                 return CompileInherentImplItem::Compile (impl_item, ctx,
     393            0 :                                                          nullptr, expr_locus);
     394              :               else
     395          141 :                 return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
     396          141 :                                                          expr_locus);
     397              :             }
     398          251 :         }
     399              :     }
     400              : 
     401            2 :   return error_mark_node;
     402              : }
     403              : 
     404              : } // namespace Compile
     405              : } // namespace Rust
        

Generated by: LCOV version 2.5.0-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.