Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : 35332650 : class CanonicalPath
47 : : {
48 : : public:
49 : 69342589 : CanonicalPath (const CanonicalPath &other)
50 : 69366657 : : segs (other.segs), crate_num (other.crate_num)
51 : : {}
52 : :
53 : 53615 : CanonicalPath &operator= (const CanonicalPath &other)
54 : : {
55 : 53615 : segs = other.segs;
56 : 53615 : crate_num = other.crate_num;
57 : 53615 : return *this;
58 : : }
59 : :
60 : 33343180 : static CanonicalPath new_seg (NodeId id, const std::string &path)
61 : : {
62 : 33343180 : rust_assert (!path.empty ());
63 : 33343180 : return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
64 : 100029540 : UNKNOWN_CRATENUM);
65 : : }
66 : :
67 : : static CanonicalPath
68 : 12064 : trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
69 : : const CanonicalPath &impl_type_seg)
70 : : {
71 : 24128 : return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
72 : 36192 : + trait_seg.get () + ">");
73 : : }
74 : :
75 : 1769 : static CanonicalPath inherent_impl_seg (NodeId id,
76 : : const CanonicalPath &impl_type_seg)
77 : : {
78 : 3538 : return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">");
79 : : }
80 : :
81 : 3305909 : std::string get () const
82 : : {
83 : 3305909 : std::string buf;
84 : 7138003 : for (size_t i = 0; i < segs.size (); i++)
85 : : {
86 : 3832094 : bool have_more = (i + 1) < segs.size ();
87 : 3832094 : const std::string &seg = segs.at (i).second;
88 : 10966142 : buf += seg + (have_more ? "::" : "");
89 : : }
90 : 3305909 : return buf;
91 : : }
92 : :
93 : 4257 : static CanonicalPath get_big_self (NodeId id)
94 : : {
95 : 4257 : return CanonicalPath::new_seg (id, "Self");
96 : : }
97 : :
98 : 1173384 : static CanonicalPath create_empty ()
99 : : {
100 : 1173384 : return CanonicalPath ({}, UNKNOWN_CRATENUM);
101 : : }
102 : :
103 : 32568 : bool is_empty () const { return segs.size () == 0; }
104 : :
105 : 103895 : CanonicalPath append (const CanonicalPath &other) const
106 : : {
107 : 103895 : rust_assert (!other.is_empty ());
108 : 103895 : if (is_empty ())
109 : 72562 : return CanonicalPath (other.segs, crate_num);
110 : :
111 : 67614 : std::vector<std::pair<NodeId, std::string>> copy (segs);
112 : 135256 : for (auto &s : other.segs)
113 : 67642 : copy.push_back (s);
114 : :
115 : 67614 : return CanonicalPath (copy, crate_num);
116 : 67614 : }
117 : :
118 : : // if we have the path A::B::C this will give a callback for each segment
119 : : // including the prefix, example:
120 : : //
121 : : // path:
122 : : // A::B::C
123 : : //
124 : : // iterate:
125 : : // A
126 : : // A::B
127 : : // A::B::C
128 : : void iterate (std::function<bool (const CanonicalPath &)> cb) const
129 : : {
130 : : std::vector<std::pair<NodeId, std::string>> buf;
131 : : for (auto &seg : segs)
132 : : {
133 : : buf.push_back (seg);
134 : : if (!cb (CanonicalPath (buf, crate_num)))
135 : : return;
136 : : }
137 : : }
138 : :
139 : : // if we have the path A::B::C this will give a callback for each segment
140 : : // example:
141 : : //
142 : : // path:
143 : : // A::B::C
144 : : //
145 : : // iterate:
146 : : // A
147 : : // B
148 : : // C
149 : 50 : void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
150 : : {
151 : 164 : for (auto &seg : segs)
152 : : {
153 : 114 : std::vector<std::pair<NodeId, std::string>> buf;
154 : 228 : buf.push_back ({seg.first, seg.second});
155 : 228 : if (!cb (CanonicalPath (buf, crate_num)))
156 : 0 : return;
157 : 114 : }
158 : : }
159 : :
160 : 90153 : size_t size () const { return segs.size (); }
161 : :
162 : 21883 : NodeId get_node_id () const
163 : : {
164 : 21883 : rust_assert (!segs.empty ());
165 : 21883 : return segs.back ().first;
166 : : }
167 : :
168 : 55245 : const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
169 : : {
170 : 55245 : rust_assert (index < size ());
171 : 55245 : return segs.at (index);
172 : : }
173 : :
174 : 12909 : bool is_equal (const CanonicalPath &b) const
175 : : {
176 : 12909 : return get ().compare (b.get ()) == 0;
177 : : }
178 : :
179 : 9554 : void set_crate_num (CrateNum n) { crate_num = n; }
180 : :
181 : 50 : CrateNum get_crate_num () const
182 : : {
183 : 50 : rust_assert (crate_num != UNKNOWN_CRATENUM);
184 : 50 : return crate_num;
185 : : }
186 : :
187 : : bool operator== (const CanonicalPath &b) const { return is_equal (b); }
188 : :
189 : 1578181 : bool operator< (const CanonicalPath &b) const { return get () < b.get (); }
190 : :
191 : : private:
192 : 34620573 : explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
193 : : CrateNum crate_num)
194 : 34620573 : : segs (path), crate_num (crate_num)
195 : : {}
196 : :
197 : : std::vector<std::pair<NodeId, std::string>> segs;
198 : : CrateNum crate_num;
199 : : };
200 : :
201 : : } // namespace Resolver
202 : : } // namespace Rust
203 : :
204 : : #endif // RUST_CANONICAL_PATH
|