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_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 174156445 : class CanonicalPath
47 : {
48 : public:
49 261291764 : CanonicalPath (const CanonicalPath &other)
50 261288774 : : segs (other.segs), crate_num (other.crate_num)
51 : {}
52 :
53 64 : CanonicalPath &operator= (const CanonicalPath &other)
54 : {
55 64 : segs = other.segs;
56 64 : crate_num = other.crate_num;
57 64 : return *this;
58 : }
59 :
60 86085658 : static CanonicalPath new_seg (NodeId id, std::string path)
61 : {
62 86085658 : rust_assert (!path.empty ());
63 86085658 : return CanonicalPath ({std::pair<NodeId, std::string> (id,
64 : std::move (path))},
65 258256974 : UNKNOWN_CRATENUM);
66 : }
67 :
68 : static CanonicalPath
69 10261 : trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
70 : const CanonicalPath &impl_type_seg)
71 : {
72 : // https://doc.rust-lang.org/reference/paths.html#canonical-paths
73 : // should be "<X>"?
74 20522 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
75 30783 : + trait_seg.get () + ">");
76 : }
77 :
78 6855 : static CanonicalPath inherent_impl_seg (NodeId id,
79 : const CanonicalPath &impl_type_seg)
80 : {
81 : // https://doc.rust-lang.org/reference/paths.html#canonical-paths
82 : // should be "<X as Y>"?
83 13710 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
84 : }
85 :
86 81162 : std::string get () const
87 : {
88 81162 : std::string buf;
89 287854 : for (size_t i = 0; i < segs.size (); i++)
90 : {
91 206692 : bool have_more = (i + 1) < segs.size ();
92 206692 : const std::string &seg = segs.at (i).second;
93 493357 : buf += seg + (have_more ? "::" : "");
94 : }
95 81162 : return buf;
96 : }
97 :
98 : static CanonicalPath get_big_self (NodeId id)
99 : {
100 : return CanonicalPath::new_seg (id, "Self");
101 : }
102 :
103 1305807 : static CanonicalPath create_empty ()
104 : {
105 1305807 : return CanonicalPath ({}, UNKNOWN_CRATENUM);
106 : }
107 :
108 658284 : bool is_empty () const { return segs.size () == 0; }
109 :
110 164571 : CanonicalPath append (const CanonicalPath &other) const
111 : {
112 164571 : rust_assert (!other.is_empty ());
113 164571 : if (is_empty ())
114 2 : return CanonicalPath (other.segs, crate_num);
115 :
116 164570 : std::vector<std::pair<NodeId, std::string>> copy (segs);
117 164570 : copy.reserve (other.segs.size ());
118 :
119 329140 : for (auto &s : other.segs)
120 164570 : copy.push_back (s);
121 :
122 164570 : return CanonicalPath (copy, crate_num);
123 164570 : }
124 :
125 : // if we have the path A::B::C this will give a callback for each segment
126 : // including the prefix, example:
127 : //
128 : // path:
129 : // A::B::C
130 : //
131 : // iterate:
132 : // A
133 : // A::B
134 : // A::B::C
135 : void iterate (std::function<bool (const CanonicalPath &)> cb) const
136 : {
137 : std::vector<std::pair<NodeId, std::string>> buf;
138 : for (auto &seg : segs)
139 : {
140 : buf.push_back (seg);
141 : if (!cb (CanonicalPath (buf, crate_num)))
142 : return;
143 : }
144 : }
145 :
146 : // if we have the path A::B::C this will give a callback for each segment
147 : // example:
148 : //
149 : // path:
150 : // A::B::C
151 : //
152 : // iterate:
153 : // A
154 : // B
155 : // C
156 25 : void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
157 : {
158 82 : for (auto &seg : segs)
159 : {
160 57 : std::vector<std::pair<NodeId, std::string>> buf;
161 114 : buf.push_back ({seg.first, seg.second});
162 114 : if (!cb (CanonicalPath (buf, crate_num)))
163 0 : return;
164 57 : }
165 : }
166 :
167 108437 : size_t size () const { return segs.size (); }
168 :
169 57 : NodeId get_node_id () const
170 : {
171 57 : rust_assert (!segs.empty ());
172 57 : return segs.back ().first;
173 : }
174 :
175 75022 : const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
176 : {
177 75022 : rust_assert (index < size ());
178 75022 : return segs.at (index);
179 : }
180 :
181 0 : bool is_equal (const CanonicalPath &b) const
182 : {
183 0 : return get ().compare (b.get ()) == 0;
184 : }
185 :
186 74527 : void set_crate_num (CrateNum n) { crate_num = n; }
187 :
188 25 : CrateNum get_crate_num () const
189 : {
190 25 : rust_assert (crate_num != UNKNOWN_CRATENUM);
191 25 : return crate_num;
192 : }
193 :
194 : bool operator== (const CanonicalPath &b) const { return is_equal (b); }
195 :
196 0 : bool operator< (const CanonicalPath &b) const { return get () < b.get (); }
197 :
198 : private:
199 87556093 : explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
200 : CrateNum crate_num)
201 87556093 : : segs (path), crate_num (crate_num)
202 : {}
203 :
204 : std::vector<std::pair<NodeId, std::string>> segs;
205 : CrateNum crate_num;
206 : };
207 :
208 : } // namespace Resolver
209 : } // namespace Rust
210 :
211 : #endif // RUST_CANONICAL_PATH
|