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 : 160839759 : class CanonicalPath
47 : : {
48 : : public:
49 : 241254068 : CanonicalPath (const CanonicalPath &other)
50 : 241251166 : : segs (other.segs), crate_num (other.crate_num)
51 : : {}
52 : :
53 : 62 : CanonicalPath &operator= (const CanonicalPath &other)
54 : : {
55 : 62 : segs = other.segs;
56 : 62 : crate_num = other.crate_num;
57 : 62 : return *this;
58 : : }
59 : :
60 : 79332185 : static CanonicalPath new_seg (NodeId id, std::string path)
61 : : {
62 : 79332185 : rust_assert (!path.empty ());
63 : 79332185 : return CanonicalPath ({std::pair<NodeId, std::string> (id,
64 : : std::move (path))},
65 : 237996555 : UNKNOWN_CRATENUM);
66 : : }
67 : :
68 : : static CanonicalPath
69 : 10225 : 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 : 20450 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
75 : 30675 : + trait_seg.get () + ">");
76 : : }
77 : :
78 : 6767 : 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 : 13534 : return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
84 : : }
85 : :
86 : 80432 : std::string get () const
87 : : {
88 : 80432 : std::string buf;
89 : 285710 : for (size_t i = 0; i < segs.size (); i++)
90 : : {
91 : 205278 : bool have_more = (i + 1) < segs.size ();
92 : 205278 : const std::string &seg = segs.at (i).second;
93 : 489922 : buf += seg + (have_more ? "::" : "");
94 : : }
95 : 80432 : return buf;
96 : : }
97 : :
98 : 0 : static CanonicalPath get_big_self (NodeId id)
99 : : {
100 : 0 : return CanonicalPath::new_seg (id, "Self");
101 : : }
102 : :
103 : 1429001 : static CanonicalPath create_empty ()
104 : : {
105 : 1429001 : return CanonicalPath ({}, UNKNOWN_CRATENUM);
106 : : }
107 : :
108 : 652196 : bool is_empty () const { return segs.size () == 0; }
109 : :
110 : 163049 : CanonicalPath append (const CanonicalPath &other) const
111 : : {
112 : 163049 : rust_assert (!other.is_empty ());
113 : 163049 : if (is_empty ())
114 : 2 : return CanonicalPath (other.segs, crate_num);
115 : :
116 : 163048 : std::vector<std::pair<NodeId, std::string>> copy (segs);
117 : 326096 : for (auto &s : other.segs)
118 : 163048 : copy.push_back (s);
119 : :
120 : 163048 : return CanonicalPath (copy, crate_num);
121 : 163048 : }
122 : :
123 : : // if we have the path A::B::C this will give a callback for each segment
124 : : // including the prefix, example:
125 : : //
126 : : // path:
127 : : // A::B::C
128 : : //
129 : : // iterate:
130 : : // A
131 : : // A::B
132 : : // A::B::C
133 : : void iterate (std::function<bool (const CanonicalPath &)> cb) const
134 : : {
135 : : std::vector<std::pair<NodeId, std::string>> buf;
136 : : for (auto &seg : segs)
137 : : {
138 : : buf.push_back (seg);
139 : : if (!cb (CanonicalPath (buf, crate_num)))
140 : : return;
141 : : }
142 : : }
143 : :
144 : : // if we have the path A::B::C this will give a callback for each segment
145 : : // example:
146 : : //
147 : : // path:
148 : : // A::B::C
149 : : //
150 : : // iterate:
151 : : // A
152 : : // B
153 : : // C
154 : 25 : void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
155 : : {
156 : 82 : for (auto &seg : segs)
157 : : {
158 : 57 : std::vector<std::pair<NodeId, std::string>> buf;
159 : 114 : buf.push_back ({seg.first, seg.second});
160 : 114 : if (!cb (CanonicalPath (buf, crate_num)))
161 : 0 : return;
162 : 57 : }
163 : : }
164 : :
165 : 107366 : size_t size () const { return segs.size (); }
166 : :
167 : 57 : NodeId get_node_id () const
168 : : {
169 : 57 : rust_assert (!segs.empty ());
170 : 57 : return segs.back ().first;
171 : : }
172 : :
173 : 74388 : const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
174 : : {
175 : 74388 : rust_assert (index < size ());
176 : 74388 : return segs.at (index);
177 : : }
178 : :
179 : 0 : bool is_equal (const CanonicalPath &b) const
180 : : {
181 : 0 : return get ().compare (b.get ()) == 0;
182 : : }
183 : :
184 : 73606 : void set_crate_num (CrateNum n) { crate_num = n; }
185 : :
186 : 25 : CrateNum get_crate_num () const
187 : : {
188 : 25 : rust_assert (crate_num != UNKNOWN_CRATENUM);
189 : 25 : return crate_num;
190 : : }
191 : :
192 : : bool operator== (const CanonicalPath &b) const { return is_equal (b); }
193 : :
194 : 0 : bool operator< (const CanonicalPath &b) const { return get () < b.get (); }
195 : :
196 : : private:
197 : 80924292 : explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
198 : : CrateNum crate_num)
199 : 80924292 : : segs (path), crate_num (crate_num)
200 : : {}
201 : :
202 : : std::vector<std::pair<NodeId, std::string>> segs;
203 : : CrateNum crate_num;
204 : : };
205 : :
206 : : } // namespace Resolver
207 : : } // namespace Rust
208 : :
209 : : #endif // RUST_CANONICAL_PATH
|