LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 63.4 % 161 102
Test Date: 2026-02-28 14:20:25 Functions: 69.2 % 26 18
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* General AST-related method implementations for Rust frontend.
       2              :    Copyright (C) 2009-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "rust-path.h"
      21              : #include "rust-system.h"
      22              : #include "rust-ast-full.h"
      23              : #include "rust-diagnostics.h"
      24              : #include "rust-ast-visitor.h"
      25              : #include "rust-macro.h"
      26              : #include "rust-session-manager.h"
      27              : #include "rust-lex.h"
      28              : #include "rust-parse.h"
      29              : #include "rust-operators.h"
      30              : 
      31              : namespace Rust {
      32              : namespace AST {
      33              : 
      34              : std::string
      35            0 : GenericArgs::as_string () const
      36              : {
      37            0 :   std::string args;
      38              : 
      39              :   // lifetime args
      40            0 :   if (!lifetime_args.empty ())
      41              :     {
      42              :       auto i = lifetime_args.begin ();
      43              :       auto e = lifetime_args.end ();
      44              : 
      45            0 :       for (; i != e; i++)
      46              :         {
      47            0 :           args += (*i).as_string ();
      48            0 :           if (e != i + 1)
      49            0 :             args += ", ";
      50              :         }
      51              :     }
      52              : 
      53              :   // type args
      54            0 :   if (!generic_args.empty ())
      55              :     {
      56              :       auto i = generic_args.begin ();
      57              :       auto e = generic_args.end ();
      58              : 
      59            0 :       for (; i != e; i++)
      60              :         {
      61            0 :           args += (*i).as_string ();
      62            0 :           if (e != i + 1)
      63            0 :             args += ", ";
      64              :         }
      65              :     }
      66              : 
      67              :   // binding args
      68            0 :   if (!binding_args.empty ())
      69              :     {
      70              :       auto i = binding_args.begin ();
      71              :       auto e = binding_args.end ();
      72              : 
      73            0 :       for (; i != e; i++)
      74              :         {
      75            0 :           args += (*i).as_string ();
      76            0 :           if (e != i + 1)
      77            0 :             args += ", ";
      78              :         }
      79              :     }
      80              : 
      81            0 :   return args;
      82              : }
      83              : 
      84              : GenericArg
      85           31 : GenericArg::disambiguate_to_const () const
      86              : {
      87           31 :   rust_assert (get_kind () == Kind::Either);
      88              : 
      89              :   // FIXME: is it fine to have no outer attributes?
      90           31 :   return GenericArg::create_const (
      91           31 :     std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
      92              : }
      93              : 
      94              : GenericArg
      95         2316 : GenericArg::disambiguate_to_type () const
      96              : {
      97         2316 :   rust_assert (get_kind () == Kind::Either);
      98              : 
      99         2316 :   auto segment = std::unique_ptr<TypePathSegment> (
     100         4632 :     new TypePathSegment (path.as_string (), false, locus));
     101         2316 :   auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
     102         2316 :   segments.emplace_back (std::move (segment));
     103              : 
     104         2316 :   return GenericArg::create_type (
     105         2316 :     std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
     106         2316 : }
     107              : 
     108              : std::string
     109            0 : GenericArgsBinding::as_string () const
     110              : {
     111              :   // TODO: rewrite to work with non-literalisable types
     112            0 :   return identifier.as_string () + " = " + type->as_string ();
     113              : }
     114              : 
     115              : std::string
     116            0 : ConstGenericParam::as_string () const
     117              : {
     118            0 :   std::string str ("ConstGenericParam: ");
     119            0 :   str += "const " + name.as_string () + ": " + type->as_string ();
     120              : 
     121            0 :   if (has_default_value ())
     122            0 :     str += " = " + get_default_value_unchecked ().as_string ();
     123              : 
     124            0 :   return str;
     125              : }
     126              : 
     127              : std::string
     128         2484 : PathExprSegment::as_string () const
     129              : {
     130              :   // TODO: rewrite dump to work with non-literalisable types
     131         2484 :   std::string ident_str = segment_name.as_string ();
     132         2484 :   if (has_generic_args ())
     133            0 :     ident_str += "::<" + generic_args.as_string () + ">";
     134              : 
     135         2484 :   return ident_str;
     136              : }
     137              : 
     138              : std::string
     139            1 : Path::as_string () const
     140              : {
     141              :   // FIXME: Impl for lang items
     142            1 :   rust_assert (kind == Kind::Regular);
     143              : 
     144            1 :   std::string str;
     145              : 
     146            2 :   for (const auto &segment : segments)
     147            3 :     str += segment.as_string () + "::";
     148              : 
     149              :   // basically a hack - remove last two characters of string (remove final ::)
     150            1 :   str.erase (str.length () - 2);
     151              : 
     152            1 :   return str;
     153              : }
     154              : 
     155              : SimplePath
     156         2460 : Path::convert_to_simple_path (bool with_opening_scope_resolution) const
     157              : {
     158         2460 :   rust_assert (kind == Kind::Regular);
     159              : 
     160         2460 :   if (!has_segments ())
     161            0 :     return SimplePath::create_empty ();
     162              : 
     163              :   // create vector of reserved size (to minimise reallocations)
     164         2460 :   std::vector<SimplePathSegment> simple_segments;
     165         2460 :   simple_segments.reserve (segments.size ());
     166              : 
     167         4943 :   for (const auto &segment : segments)
     168              :     {
     169              :       // return empty path if doesn't meet simple path segment requirements
     170         2483 :       if (segment.is_error () || segment.has_generic_args ())
     171            0 :         return SimplePath::create_empty ();
     172              : 
     173              :       // create segment and add to vector
     174         2483 :       std::string segment_str = segment.as_string ();
     175         2483 :       simple_segments.emplace_back (std::move (segment_str),
     176         2483 :                                     segment.get_locus ());
     177         2483 :     }
     178              : 
     179              :   // kind of a HACK to get locus depending on opening scope resolution
     180         2460 :   location_t locus = UNKNOWN_LOCATION;
     181         2460 :   if (with_opening_scope_resolution)
     182            0 :     locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
     183              :   else
     184         2460 :     locus = simple_segments[0].get_locus ();
     185              :   // FIXME: this hack probably doesn't actually work
     186              : 
     187         2460 :   return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
     188         2460 :                      locus);
     189         2460 : }
     190              : 
     191              : void
     192       472989 : PathInExpression::accept_vis (ASTVisitor &vis)
     193              : {
     194       472989 :   vis.visit (*this);
     195       472989 : }
     196              : 
     197              : std::string
     198            1 : PathInExpression::as_string () const
     199              : {
     200            1 :   std::string str;
     201              : 
     202            1 :   if (has_opening_scope_resolution)
     203            0 :     str = "::";
     204              : 
     205            1 :   return str + Path::as_string ();
     206            1 : }
     207              : 
     208              : std::string
     209            0 : TypePathSegmentGeneric::as_string () const
     210              : {
     211              :   // TODO: rewrite to work with non-linearisable types
     212            0 :   return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
     213              : }
     214              : 
     215              : std::string
     216            0 : TypePathSegmentFunction::as_string () const
     217              : {
     218              :   // TODO: rewrite to work with non-linearisable types
     219            0 :   return TypePathSegment::as_string () + function_path.as_string ();
     220              : }
     221              : 
     222              : std::string
     223          258 : TypePath::as_string () const
     224              : {
     225              :   /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
     226              :    * literalised */
     227          258 :   std::string str;
     228              : 
     229          258 :   if (has_opening_scope_resolution)
     230            0 :     str = "::";
     231              : 
     232          516 :   for (const auto &segment : segments)
     233          774 :     str += segment->as_string () + "::";
     234              : 
     235              :   // kinda hack - remove last 2 '::' characters
     236          258 :   str.erase (str.length () - 2);
     237              : 
     238          258 :   return str;
     239              : }
     240              : 
     241              : SimplePath
     242           30 : TypePath::as_simple_path () const
     243              : {
     244           30 :   if (segments.empty ())
     245            0 :     return SimplePath::create_empty ();
     246              : 
     247              :   // create vector of reserved size (to minimise reallocations)
     248           30 :   std::vector<SimplePathSegment> simple_segments;
     249           30 :   simple_segments.reserve (segments.size ());
     250              : 
     251           60 :   for (const auto &segment : segments)
     252              :     {
     253              :       // return empty path if doesn't meet simple path segment requirements
     254           30 :       if (segment == nullptr || segment->is_error ()
     255           60 :           || !segment->is_ident_only () || segment->as_string () == "Self")
     256            0 :         return SimplePath::create_empty ();
     257              : 
     258              :       // create segment and add to vector
     259           30 :       std::string segment_str = segment->as_string ();
     260           30 :       simple_segments.emplace_back (std::move (segment_str),
     261           30 :                                     segment->get_locus ());
     262           30 :     }
     263              : 
     264           30 :   return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
     265           30 :                      locus);
     266           30 : }
     267              : 
     268              : std::string
     269           25 : TypePath::make_debug_string () const
     270              : {
     271           25 :   rust_assert (!segments.empty ());
     272              : 
     273           25 :   std::string output;
     274              : 
     275           50 :   for (const auto &segment : segments)
     276              :     {
     277           25 :       if (segment != nullptr && !segment->is_lang_item ()
     278           50 :           && !segment->is_error ())
     279              :         {
     280           25 :           if (!output.empty () || has_opening_scope_resolution_op ())
     281            0 :             output.append ("::");
     282           75 :           output.append (segment->get_ident_segment ().as_string ());
     283              :         }
     284              :     }
     285              : 
     286           25 :   return output;
     287              : }
     288              : 
     289              : // hopefully definition here will prevent circular dependency issue
     290              : TraitBound *
     291            3 : TypePath::to_trait_bound (bool in_parens) const
     292              : {
     293              :   // If already in parentheses, don't convert to trait bound
     294              :   // This ensures (TypePath) stays as ParenthesisedType in the parser
     295            3 :   if (in_parens)
     296              :     return nullptr;
     297              : 
     298            0 :   return new TraitBound (TypePath (*this), get_locus (), in_parens);
     299              : }
     300              : 
     301              : std::string
     302            0 : TypePathFunction::as_string () const
     303              : {
     304              :   // TODO: rewrite to work with non-linearisable types
     305            0 :   std::string str ("(");
     306              : 
     307            0 :   if (has_inputs ())
     308              :     {
     309              :       auto i = inputs.begin ();
     310              :       auto e = inputs.end ();
     311              : 
     312            0 :       for (; i != e; i++)
     313              :         {
     314            0 :           str += (*i)->as_string ();
     315            0 :           if (e != i + 1)
     316            0 :             str += ", ";
     317              :         }
     318              :     }
     319              : 
     320            0 :   str += ")";
     321              : 
     322            0 :   if (has_return_type ())
     323            0 :     str += " -> " + return_type->as_string ();
     324              : 
     325            0 :   return str;
     326              : }
     327              : 
     328              : std::string
     329            0 : QualifiedPathInExpression::as_string () const
     330              : {
     331            0 :   return path_type.as_string () + "::" + Path::as_string ();
     332              : }
     333              : 
     334              : std::string
     335            0 : QualifiedPathInType::as_string () const
     336              : {
     337              :   /* TODO: this may need adjusting if segments (e.g. with functions) can't be
     338              :    * literalised */
     339            0 :   std::string str = path_type.as_string ();
     340              : 
     341            0 :   str += "::" + associated_segment->as_string ();
     342            0 :   for (const auto &segment : segments)
     343            0 :     str += "::" + segment->as_string ();
     344              : 
     345            0 :   return str;
     346              : }
     347              : 
     348              : void
     349         1555 : ConstGenericParam::accept_vis (ASTVisitor &vis)
     350              : {
     351         1555 :   vis.visit (*this);
     352         1555 : }
     353              : 
     354              : void
     355      1057431 : TypePathSegment::accept_vis (ASTVisitor &vis)
     356              : {
     357      1057431 :   vis.visit (*this);
     358      1057431 : }
     359              : 
     360              : void
     361        55954 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
     362              : {
     363        55954 :   vis.visit (*this);
     364        55954 : }
     365              : 
     366              : void
     367          474 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
     368              : {
     369          474 :   vis.visit (*this);
     370          474 : }
     371              : 
     372              : void
     373       989153 : TypePath::accept_vis (ASTVisitor &vis)
     374              : {
     375       989153 :   vis.visit (*this);
     376       989153 : }
     377              : 
     378              : void
     379         2235 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
     380              : {
     381         2235 :   vis.visit (*this);
     382         2235 : }
     383              : 
     384              : void
     385         5905 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
     386              : {
     387         5905 :   vis.visit (*this);
     388         5905 : }
     389              : 
     390              : } // namespace AST
     391              : } // namespace Rust
        

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.