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 : 13935634 : class CanonicalPath
47 : : {
48 : : public:
49 : 26960947 : CanonicalPath (const CanonicalPath &other) : segs (other.segs) {}
50 : :
51 : 33534 : CanonicalPath &operator= (const CanonicalPath &other)
52 : : {
53 : 33534 : segs = other.segs;
54 : 33534 : crate_num = other.crate_num;
55 : 33534 : return *this;
56 : : }
57 : :
58 : 12655814 : static CanonicalPath new_seg (NodeId id, const std::string &path)
59 : : {
60 : 12655814 : rust_assert (!path.empty ());
61 : 12655814 : return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
62 : 37967442 : UNKNOWN_CRATENUM);
63 : : }
64 : :
65 : : static CanonicalPath
66 : 6998 : trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
67 : : const CanonicalPath &impl_type_seg)
68 : : {
69 : 13996 : return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
70 : 20994 : + trait_seg.get () + ">");
71 : : }
72 : :
73 : 1470 : static CanonicalPath inherent_impl_seg (NodeId id,
74 : : const CanonicalPath &impl_type_seg)
75 : : {
76 : 2940 : return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">");
77 : : }
78 : :
79 : 2576558 : std::string get () const
80 : : {
81 : 2576558 : std::string buf;
82 : 5402062 : for (size_t i = 0; i < segs.size (); i++)
83 : : {
84 : 2825504 : bool have_more = (i + 1) < segs.size ();
85 : 2825504 : const std::string &seg = segs.at (i).second;
86 : 5402062 : buf += seg + (have_more ? "::" : "");
87 : : }
88 : 2576558 : return buf;
89 : : }
90 : :
91 : 5098 : static CanonicalPath get_big_self (NodeId id)
92 : : {
93 : 5098 : return CanonicalPath::new_seg (id, "Self");
94 : : }
95 : :
96 : 755616 : static CanonicalPath create_empty ()
97 : : {
98 : 755616 : return CanonicalPath ({}, UNKNOWN_CRATENUM);
99 : : }
100 : :
101 : 23766 : bool is_empty () const { return segs.size () == 0; }
102 : :
103 : 70809 : CanonicalPath append (const CanonicalPath &other) const
104 : : {
105 : 70809 : rust_assert (!other.is_empty ());
106 : 70809 : if (is_empty ())
107 : 61554 : return CanonicalPath (other.segs, crate_num);
108 : :
109 : 40032 : std::vector<std::pair<NodeId, std::string>> copy (segs);
110 : 80089 : for (auto &s : other.segs)
111 : 40057 : copy.push_back (s);
112 : :
113 : 40032 : return CanonicalPath (copy, crate_num);
114 : 40032 : }
115 : :
116 : : // if we have the path A::B::C this will give a callback for each segment
117 : : // including the prefix, example:
118 : : //
119 : : // path:
120 : : // A::B::C
121 : : //
122 : : // iterate:
123 : : // A
124 : : // A::B
125 : : // A::B::C
126 : : void iterate (std::function<bool (const CanonicalPath &)> cb) const
127 : : {
128 : : std::vector<std::pair<NodeId, std::string>> buf;
129 : : for (auto &seg : segs)
130 : : {
131 : : buf.push_back (seg);
132 : : if (!cb (CanonicalPath (buf, crate_num)))
133 : : return;
134 : : }
135 : : }
136 : :
137 : : // if we have the path A::B::C this will give a callback for each segment
138 : : // example:
139 : : //
140 : : // path:
141 : : // A::B::C
142 : : //
143 : : // iterate:
144 : : // A
145 : : // B
146 : : // C
147 : 25 : void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
148 : : {
149 : 82 : for (auto &seg : segs)
150 : : {
151 : 57 : std::vector<std::pair<NodeId, std::string>> buf;
152 : 57 : buf.push_back ({seg.first, seg.second});
153 : 114 : if (!cb (CanonicalPath (buf, crate_num)))
154 : 0 : return;
155 : 57 : }
156 : : }
157 : :
158 : 53341 : size_t size () const { return segs.size (); }
159 : :
160 : 17455 : NodeId get_node_id () const
161 : : {
162 : 17455 : rust_assert (!segs.empty ());
163 : 17455 : return segs.back ().first;
164 : : }
165 : :
166 : 31721 : const std::pair<NodeId, std::string> &get_seg_at (size_t index) const
167 : : {
168 : 31721 : rust_assert (index < size ());
169 : 31721 : return segs.at (index);
170 : : }
171 : :
172 : 10310 : bool is_equal (const CanonicalPath &b) const
173 : : {
174 : 10310 : return get ().compare (b.get ()) == 0;
175 : : }
176 : :
177 : 3605 : void set_crate_num (CrateNum n) { crate_num = n; }
178 : :
179 : 25 : CrateNum get_crate_num () const
180 : : {
181 : 25 : rust_assert (crate_num != UNKNOWN_CRATENUM);
182 : 25 : return crate_num;
183 : : }
184 : :
185 : : bool operator== (const CanonicalPath &b) const { return is_equal (b); }
186 : :
187 : 1246510 : bool operator< (const CanonicalPath &b) const { return get () < b.get (); }
188 : :
189 : : private:
190 : 13482296 : explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path,
191 : : CrateNum crate_num)
192 : 13482296 : : segs (path), crate_num (crate_num)
193 : : {}
194 : :
195 : : std::vector<std::pair<NodeId, std::string>> segs;
196 : : CrateNum crate_num;
197 : : };
198 : :
199 : : } // namespace Resolver
200 : : } // namespace Rust
201 : :
202 : : #endif // RUST_CANONICAL_PATH
|