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 : 174350909 : class CanonicalPath
47 : : {
48 : : public:
49 : 261463764 : CanonicalPath (const CanonicalPath &other)
50 : 261460827 : : 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 : 86148628 : static CanonicalPath new_seg (NodeId id, std::string path)
61 : : {
62 : 86148628 : rust_assert (!path.empty ());
63 : 86148628 : return CanonicalPath ({std::pair<NodeId, std::string> (id,
64 : : std::move (path))},
65 : 258445884 : UNKNOWN_CRATENUM);
66 : : }
67 : :
68 : : static CanonicalPath
69 : 10246 : 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 : 20492 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
75 : 30738 : + trait_seg.get () + ">");
76 : : }
77 : :
78 : 6771 : 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 : 13542 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
84 : : }
85 : :
86 : 80662 : std::string get () const
87 : : {
88 : 80662 : std::string buf;
89 : 286514 : for (size_t i = 0; i < segs.size (); i++)
90 : : {
91 : 205852 : bool have_more = (i + 1) < segs.size ();
92 : 205852 : const std::string &seg = segs.at (i).second;
93 : 491279 : buf += seg + (have_more ? "::" : "");
94 : : }
95 : 80662 : return buf;
96 : : }
97 : :
98 : : static CanonicalPath get_big_self (NodeId id)
99 : : {
100 : : return CanonicalPath::new_seg (id, "Self");
101 : : }
102 : :
103 : 1377142 : static CanonicalPath create_empty ()
104 : : {
105 : 1377142 : return CanonicalPath ({}, UNKNOWN_CRATENUM);
106 : : }
107 : :
108 : 655548 : bool is_empty () const { return segs.size () == 0; }
109 : :
110 : 163887 : CanonicalPath append (const CanonicalPath &other) const
111 : : {
112 : 163887 : rust_assert (!other.is_empty ());
113 : 163887 : if (is_empty ())
114 : 2 : return CanonicalPath (other.segs, crate_num);
115 : :
116 : 163886 : std::vector<std::pair<NodeId, std::string>> copy (segs);
117 : 163886 : copy.reserve (other.segs.size ());
118 : :
119 : 327772 : for (auto &s : other.segs)
120 : 163886 : copy.push_back (s);
121 : :
122 : 163886 : return CanonicalPath (copy, crate_num);
123 : 163886 : }
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 : 107736 : 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 : 74614 : const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
176 : : {
177 : 74614 : rust_assert (index < size ());
178 : 74614 : 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 : 73970 : 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 : 87689714 : explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
200 : : CrateNum crate_num)
201 : 87689714 : : 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
|