(root)/
gcc-13.2.0/
gcc/
rust/
util/
rust-canonical-path.h
       1  // Copyright (C) 2020-2023 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_CANONICAL_PATH
      20  #define RUST_CANONICAL_PATH
      21  
      22  #include "rust-system.h"
      23  #include "rust-mapping-common.h"
      24  
      25  namespace Rust {
      26  namespace Resolver {
      27  
      28  // https://doc.rust-lang.org/reference/paths.html#canonical-paths
      29  //
      30  // struct X - path X
      31  // impl X { fn test - path X::test }
      32  //
      33  // struct X<T> - path X
      34  //
      35  // impl X<T>   { fn test - path X::test}
      36  // impl X<i32> { fn test - path X<i32>::test }
      37  // impl X<f32> { fn test - path X<f32>::test }
      38  //
      39  // pub trait Trait { // ::a::Trait
      40  //   fn f(&self); // ::a::Trait::f
      41  // }
      42  //
      43  // impl Trait for Struct {
      44  //    fn f(&self) {} // <::a::Struct as ::a::Trait>::f
      45  // }
      46  class CanonicalPath
      47  {
      48  public:
      49    CanonicalPath (const CanonicalPath &other) : segs (other.segs) {}
      50  
      51    CanonicalPath &operator= (const CanonicalPath &other)
      52    {
      53      segs = other.segs;
      54      return *this;
      55    }
      56  
      57    static CanonicalPath new_seg (NodeId id, const std::string &path)
      58    {
      59      rust_assert (!path.empty ());
      60      return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
      61  			  UNKNOWN_CREATENUM);
      62    }
      63  
      64    static CanonicalPath
      65    trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
      66  			     const CanonicalPath &impl_type_seg)
      67    {
      68      return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
      69  					 + trait_seg.get () + ">");
      70    }
      71  
      72    std::string get () const
      73    {
      74      std::string buf;
      75      for (size_t i = 0; i < segs.size (); i++)
      76        {
      77  	bool have_more = (i + 1) < segs.size ();
      78  	const std::string &seg = segs.at (i).second;
      79  	buf += seg + (have_more ? "::" : "");
      80        }
      81      return buf;
      82    }
      83  
      84    static CanonicalPath get_big_self (NodeId id)
      85    {
      86      return CanonicalPath::new_seg (id, "Self");
      87    }
      88  
      89    static CanonicalPath create_empty ()
      90    {
      91      return CanonicalPath ({}, UNKNOWN_CREATENUM);
      92    }
      93  
      94    bool is_empty () const { return segs.size () == 0; }
      95  
      96    CanonicalPath append (const CanonicalPath &other) const
      97    {
      98      rust_assert (!other.is_empty ());
      99      if (is_empty ())
     100        return CanonicalPath (other.segs, crate_num);
     101  
     102      std::vector<std::pair<NodeId, std::string>> copy (segs);
     103      for (auto &s : other.segs)
     104        copy.push_back (s);
     105  
     106      return CanonicalPath (copy, crate_num);
     107    }
     108  
     109    // if we have the path A::B::C this will give a callback for each segment
     110    // including the prefix, example:
     111    //
     112    // path:
     113    //   A::B::C
     114    //
     115    // iterate:
     116    //   A
     117    //   A::B
     118    //   A::B::C
     119    void iterate (std::function<bool (const CanonicalPath &)> cb) const
     120    {
     121      std::vector<std::pair<NodeId, std::string>> buf;
     122      for (auto &seg : segs)
     123        {
     124  	buf.push_back (seg);
     125  	if (!cb (CanonicalPath (buf, crate_num)))
     126  	  return;
     127        }
     128    }
     129  
     130    // if we have the path A::B::C this will give a callback for each segment
     131    // example:
     132    //
     133    // path:
     134    //   A::B::C
     135    //
     136    // iterate:
     137    //   A
     138    //      B
     139    //         C
     140    void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
     141    {
     142      for (auto &seg : segs)
     143        {
     144  	std::vector<std::pair<NodeId, std::string>> buf;
     145  	buf.push_back ({seg.first, seg.second});
     146  	if (!cb (CanonicalPath (buf, crate_num)))
     147  	  return;
     148        }
     149    }
     150  
     151    size_t size () const { return segs.size (); }
     152  
     153    NodeId get_node_id () const
     154    {
     155      rust_assert (!segs.empty ());
     156      return segs.back ().first;
     157    }
     158  
     159    const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
     160    {
     161      rust_assert (index < size ());
     162      return segs.at (index);
     163    }
     164  
     165    bool is_equal (const CanonicalPath &b) const
     166    {
     167      return get ().compare (b.get ()) == 0;
     168    }
     169  
     170    void set_crate_num (CrateNum n) { crate_num = n; }
     171  
     172    CrateNum get_crate_num () const
     173    {
     174      rust_assert (crate_num != UNKNOWN_CREATENUM);
     175      return crate_num;
     176    }
     177  
     178    bool operator== (const CanonicalPath &b) const { return is_equal (b); }
     179  
     180    bool operator< (const CanonicalPath &b) const { return get () < b.get (); }
     181  
     182  private:
     183    explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
     184  			  CrateNum crate_num)
     185      : segs (path), crate_num (crate_num)
     186    {}
     187  
     188    std::vector<std::pair<NodeId, std::string>> segs;
     189    CrateNum crate_num;
     190  };
     191  
     192  } // namespace Resolver
     193  } // namespace Rust
     194  
     195  #endif // RUST_CANONICAL_PATH