LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 59.3 % 172 102
Test Date: 2026-09-19 16:22:48 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            0 :       auto i = lifetime_args.begin ();
      43            0 :       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            0 :       auto i = generic_args.begin ();
      57            0 :       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            0 :       auto i = binding_args.begin ();
      71            0 :       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           66 : GenericArg::disambiguate_to_const () const
      86              : {
      87           66 :   rust_assert (get_kind () == Kind::Either);
      88              : 
      89              :   // FIXME: is it fine to have no outer attributes?
      90           66 :   return GenericArg::create_const (
      91           66 :     std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
      92              : }
      93              : 
      94              : GenericArg
      95        12398 : GenericArg::disambiguate_to_type () const
      96              : {
      97        12398 :   rust_assert (get_kind () == Kind::Either);
      98              : 
      99        12398 :   auto segment = std::unique_ptr<TypePathSegment> (
     100        24796 :     new TypePathSegment (path.as_string (), false, locus));
     101        12398 :   auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
     102        12398 :   segments.emplace_back (std::move (segment));
     103              : 
     104        12398 :   return GenericArg::create_type (
     105        12398 :     std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
     106        12398 : }
     107              : 
     108              : std::string
     109            0 : GenericArgsBinding::as_string () const
     110              : {
     111            0 :   auto type_string = type->as_string ();
     112            0 :   auto separator = kind == Kind::Constraint ? " : " : " = ";
     113            0 :   return identifier.as_string () + separator + type_string;
     114            0 : }
     115              : 
     116              : std::string
     117            0 : ConstGenericParam::as_string () const
     118              : {
     119            0 :   std::string str ("ConstGenericParam: ");
     120            0 :   str += "const " + name.as_string () + ": " + type->as_string ();
     121              : 
     122            0 :   if (has_default_value ())
     123            0 :     str += " = " + get_default_value_unchecked ().as_string ();
     124              : 
     125            0 :   return str;
     126              : }
     127              : 
     128              : std::string
     129        55846 : PathExprSegment::as_string () const
     130              : {
     131              :   // TODO: rewrite dump to work with non-literalisable types
     132        55846 :   std::string ident_str = segment_name.as_string ();
     133        55846 :   if (has_generic_args ())
     134            0 :     ident_str += "::<" + generic_args.as_string () + ">";
     135              : 
     136        55846 :   return ident_str;
     137              : }
     138              : 
     139              : std::string
     140            1 : Path::as_string () const
     141              : {
     142              :   // FIXME: Impl for lang items
     143            1 :   rust_assert (kind == Kind::Regular);
     144              : 
     145            1 :   std::string str;
     146              : 
     147            2 :   for (const auto &segment : segments)
     148            3 :     str += segment.as_string () + "::";
     149              : 
     150              :   // basically a hack - remove last two characters of string (remove final ::)
     151            1 :   str.erase (str.length () - 2);
     152              : 
     153            1 :   return str;
     154              : }
     155              : 
     156              : SimplePath
     157        55592 : Path::convert_to_simple_path (bool with_opening_scope_resolution) const
     158              : {
     159        55592 :   rust_assert (kind == Kind::Regular);
     160              : 
     161        55592 :   if (!has_segments ())
     162            0 :     return SimplePath::create_empty ();
     163              : 
     164              :   // create vector of reserved size (to minimise reallocations)
     165        55592 :   std::vector<SimplePathSegment> simple_segments;
     166        55592 :   simple_segments.reserve (segments.size ());
     167              : 
     168       111437 :   for (const auto &segment : segments)
     169              :     {
     170              :       // return empty path if doesn't meet simple path segment requirements
     171        55845 :       if (segment.is_error () || segment.has_generic_args ())
     172            0 :         return SimplePath::create_empty ();
     173              : 
     174              :       // create segment and add to vector
     175        55845 :       std::string segment_str = segment.as_string ();
     176        55845 :       simple_segments.emplace_back (std::move (segment_str),
     177        55845 :                                     segment.get_locus ());
     178        55845 :     }
     179              : 
     180              :   // kind of a HACK to get locus depending on opening scope resolution
     181        55592 :   location_t locus = UNKNOWN_LOCATION;
     182        55592 :   if (with_opening_scope_resolution)
     183            0 :     locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
     184              :   else
     185        55592 :     locus = simple_segments[0].get_locus ();
     186              :   // FIXME: this hack probably doesn't actually work
     187              : 
     188        55592 :   return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
     189        55592 :                      locus);
     190        55592 : }
     191              : 
     192              : void
     193     19256570 : PathInExpression::accept_vis (ASTVisitor &vis)
     194              : {
     195     19256570 :   vis.visit (*this);
     196     19256569 : }
     197              : 
     198              : std::string
     199            1 : PathInExpression::as_string () const
     200              : {
     201            1 :   std::string str;
     202              : 
     203            1 :   if (has_opening_scope_resolution)
     204            0 :     str = "::";
     205              : 
     206            1 :   return str + Path::as_string ();
     207            1 : }
     208              : 
     209              : std::string
     210            0 : TypePathSegmentGeneric::as_string () const
     211              : {
     212              :   // TODO: rewrite to work with non-linearisable types
     213            0 :   return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
     214              : }
     215              : 
     216              : std::string
     217            0 : TypePathSegmentFunction::as_string () const
     218              : {
     219              :   // TODO: rewrite to work with non-linearisable types
     220            0 :   return TypePathSegment::as_string () + function_path.as_string ();
     221              : }
     222              : 
     223              : std::string
     224         1578 : TypePath::as_string () const
     225              : {
     226              :   /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
     227              :    * literalised */
     228         1578 :   std::string str;
     229              : 
     230         1578 :   if (has_opening_scope_resolution)
     231            0 :     str = "::";
     232              : 
     233         3156 :   for (const auto &segment : segments)
     234         4734 :     str += segment->as_string () + "::";
     235              : 
     236              :   // kinda hack - remove last 2 '::' characters
     237         1578 :   str.erase (str.length () - 2);
     238              : 
     239         1578 :   return str;
     240              : }
     241              : 
     242              : SimplePath
     243          498 : TypePath::as_simple_path () const
     244              : {
     245          498 :   if (segments.empty ())
     246            0 :     return SimplePath::create_empty ();
     247              : 
     248              :   // create vector of reserved size (to minimise reallocations)
     249          498 :   std::vector<SimplePathSegment> simple_segments;
     250          498 :   simple_segments.reserve (segments.size ());
     251              : 
     252          996 :   for (const auto &segment : segments)
     253              :     {
     254              :       // return empty path if doesn't meet simple path segment requirements
     255          498 :       if (segment == nullptr || segment->is_error ()
     256          996 :           || !segment->is_ident_only () || segment->as_string () == "Self")
     257            0 :         return SimplePath::create_empty ();
     258              : 
     259              :       // create segment and add to vector
     260          498 :       std::string segment_str = segment->as_string ();
     261          498 :       simple_segments.emplace_back (std::move (segment_str),
     262          498 :                                     segment->get_locus ());
     263          498 :     }
     264              : 
     265          498 :   return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
     266          498 :                      locus);
     267          498 : }
     268              : 
     269              : std::string
     270           27 : TypePath::make_debug_string () const
     271              : {
     272           27 :   rust_assert (!segments.empty ());
     273              : 
     274           27 :   std::string output;
     275              : 
     276           54 :   for (const auto &segment : segments)
     277              :     {
     278           27 :       if (segment != nullptr && !segment->is_lang_item ()
     279           54 :           && !segment->is_error ())
     280              :         {
     281           27 :           if (!output.empty () || has_opening_scope_resolution_op ())
     282            0 :             output.append ("::");
     283           81 :           output.append (segment->get_ident_segment ().as_string ());
     284              :         }
     285              :     }
     286              : 
     287           27 :   return output;
     288              : }
     289              : 
     290              : // hopefully definition here will prevent circular dependency issue
     291              : TraitBound *
     292            3 : TypePath::to_trait_bound (bool in_parens) const
     293              : {
     294              :   // If already in parentheses, don't convert to trait bound
     295              :   // This ensures (TypePath) stays as ParenthesisedType in the parser
     296            3 :   if (in_parens)
     297              :     return nullptr;
     298              : 
     299            0 :   return new TraitBound (TypePath (*this), get_locus (), in_parens);
     300              : }
     301              : 
     302              : std::string
     303            0 : TypePathFunction::as_string () const
     304              : {
     305              :   // TODO: rewrite to work with non-linearisable types
     306            0 :   std::string str ("(");
     307              : 
     308            0 :   if (has_inputs ())
     309              :     {
     310            0 :       auto i = inputs.begin ();
     311            0 :       auto e = inputs.end ();
     312              : 
     313            0 :       for (; i != e; i++)
     314              :         {
     315            0 :           str += (*i)->as_string ();
     316            0 :           if (e != i + 1)
     317            0 :             str += ", ";
     318              :         }
     319              :     }
     320              : 
     321            0 :   str += ")";
     322              : 
     323            0 :   if (has_return_type ())
     324            0 :     str += " -> " + return_type->as_string ();
     325              : 
     326            0 :   return str;
     327              : }
     328              : 
     329              : std::string
     330            0 : QualifiedPathInExpression::as_string () const
     331              : {
     332            0 :   return path_type.as_string () + "::" + Path::as_string ();
     333              : }
     334              : 
     335              : std::string
     336            0 : QualifiedPathInType::as_string () const
     337              : {
     338              :   /* TODO: this may need adjusting if segments (e.g. with functions) can't be
     339              :    * literalised */
     340            0 :   std::string str = path_type.as_string ();
     341              : 
     342            0 :   str += "::" + associated_segment->as_string ();
     343            0 :   for (const auto &segment : segments)
     344            0 :     str += "::" + segment->as_string ();
     345              : 
     346            0 :   return str;
     347              : }
     348              : 
     349              : void
     350        19779 : ConstGenericParam::accept_vis (ASTVisitor &vis)
     351              : {
     352        19779 :   vis.visit (*this);
     353        19779 : }
     354              : 
     355              : void
     356     16569242 : TypePathSegment::accept_vis (ASTVisitor &vis)
     357              : {
     358     16569242 :   vis.visit (*this);
     359     16569242 : }
     360              : 
     361              : void
     362      3918308 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
     363              : {
     364      3918308 :   vis.visit (*this);
     365      3918308 : }
     366              : 
     367              : void
     368       137004 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
     369              : {
     370       137004 :   vis.visit (*this);
     371       137004 : }
     372              : 
     373              : void
     374     15145591 : TypePath::accept_vis (ASTVisitor &vis)
     375              : {
     376     15145591 :   vis.visit (*this);
     377     15145591 : }
     378              : 
     379              : void
     380        33089 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
     381              : {
     382        33089 :   vis.visit (*this);
     383        33089 : }
     384              : 
     385              : void
     386       751188 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
     387              : {
     388       751188 :   vis.visit (*this);
     389       751188 : }
     390              : 
     391              : } // namespace AST
     392              : } // 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.