Branch data Line data Source code
1 : : /* General AST-related method implementations for Rust frontend.
2 : : Copyright (C) 2009-2025 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "rust-path.h"
21 : : #include "rust-system.h"
22 : : #include "rust-ast-full.h"
23 : : #include "rust-diagnostics.h"
24 : : #include "rust-ast-visitor.h"
25 : : #include "rust-macro.h"
26 : : #include "rust-session-manager.h"
27 : : #include "rust-lex.h"
28 : : #include "rust-parse.h"
29 : : #include "rust-operators.h"
30 : :
31 : : namespace Rust {
32 : : namespace AST {
33 : :
34 : : std::string
35 : 705 : GenericArgs::as_string () const
36 : : {
37 : 705 : std::string args;
38 : :
39 : : // lifetime args
40 : 705 : if (!lifetime_args.empty ())
41 : : {
42 : : auto i = lifetime_args.begin ();
43 : : auto e = lifetime_args.end ();
44 : :
45 : 42 : for (; i != e; i++)
46 : : {
47 : 42 : args += (*i).as_string ();
48 : 21 : if (e != i + 1)
49 : 0 : args += ", ";
50 : : }
51 : : }
52 : :
53 : : // type args
54 : 705 : if (!generic_args.empty ())
55 : : {
56 : : auto i = generic_args.begin ();
57 : : auto e = generic_args.end ();
58 : :
59 : 1459 : for (; i != e; i++)
60 : : {
61 : 1550 : args += (*i).as_string ();
62 : 775 : if (e != i + 1)
63 : 91 : args += ", ";
64 : : }
65 : : }
66 : :
67 : : // binding args
68 : 705 : if (!binding_args.empty ())
69 : : {
70 : : auto i = binding_args.begin ();
71 : : auto e = binding_args.end ();
72 : :
73 : 0 : for (; i != e; i++)
74 : : {
75 : 0 : args += (*i).as_string ();
76 : 0 : if (e != i + 1)
77 : 0 : args += ", ";
78 : : }
79 : : }
80 : :
81 : 705 : return args;
82 : : }
83 : :
84 : : GenericArg
85 : 14 : GenericArg::disambiguate_to_const () const
86 : : {
87 : 14 : rust_assert (get_kind () == Kind::Either);
88 : :
89 : : // FIXME: is it fine to have no outer attributes?
90 : 14 : return GenericArg::create_const (
91 : 14 : std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
92 : : }
93 : :
94 : : GenericArg
95 : 2169 : GenericArg::disambiguate_to_type () const
96 : : {
97 : 2169 : rust_assert (get_kind () == Kind::Either);
98 : :
99 : 2169 : auto segment = std::unique_ptr<TypePathSegment> (
100 : 4338 : new TypePathSegment (path.as_string (), false, locus));
101 : 2169 : auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
102 : 2169 : segments.emplace_back (std::move (segment));
103 : :
104 : 2169 : return GenericArg::create_type (
105 : 2169 : std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
106 : 2169 : }
107 : :
108 : : std::string
109 : 0 : GenericArgsBinding::as_string () const
110 : : {
111 : : // TODO: rewrite to work with non-literalisable types
112 : 0 : return identifier.as_string () + " = " + type->as_string ();
113 : : }
114 : :
115 : : std::string
116 : 0 : ConstGenericParam::as_string () const
117 : : {
118 : 0 : std::string str ("ConstGenericParam: ");
119 : 0 : str += "const " + name.as_string () + ": " + type->as_string ();
120 : :
121 : 0 : if (has_default_value ())
122 : 0 : str += " = " + get_default_value_unchecked ().as_string ();
123 : :
124 : 0 : return str;
125 : : }
126 : :
127 : : std::string
128 : 7059 : PathExprSegment::as_string () const
129 : : {
130 : : // TODO: rewrite dump to work with non-literalisable types
131 : 7059 : std::string ident_str = segment_name.as_string ();
132 : 7059 : if (has_generic_args ())
133 : 0 : ident_str += "::<" + generic_args.as_string () + ">";
134 : :
135 : 7059 : return ident_str;
136 : : }
137 : :
138 : : std::string
139 : 2 : Path::as_string () const
140 : : {
141 : : // FIXME: Impl for lang items
142 : 2 : rust_assert (kind == Kind::Regular);
143 : :
144 : 2 : std::string str;
145 : :
146 : 4 : for (const auto &segment : segments)
147 : 6 : str += segment.as_string () + "::";
148 : :
149 : : // basically a hack - remove last two characters of string (remove final ::)
150 : 2 : str.erase (str.length () - 2);
151 : :
152 : 2 : return str;
153 : : }
154 : :
155 : : SimplePath
156 : 3481 : Path::convert_to_simple_path (bool with_opening_scope_resolution) const
157 : : {
158 : 3481 : rust_assert (kind == Kind::Regular);
159 : :
160 : 3481 : if (!has_segments ())
161 : 0 : return SimplePath::create_empty ();
162 : :
163 : : // create vector of reserved size (to minimise reallocations)
164 : 3481 : std::vector<SimplePathSegment> simple_segments;
165 : 3481 : simple_segments.reserve (segments.size ());
166 : :
167 : 7008 : for (const auto &segment : segments)
168 : : {
169 : : // return empty path if doesn't meet simple path segment requirements
170 : 10581 : if (segment.is_error () || segment.has_generic_args ()
171 : 7054 : || segment.as_string () == "Self")
172 : 0 : return SimplePath::create_empty ();
173 : :
174 : : // create segment and add to vector
175 : 3527 : std::string segment_str = segment.as_string ();
176 : 7054 : simple_segments.push_back (
177 : 7054 : SimplePathSegment (std::move (segment_str), segment.get_locus ()));
178 : 3527 : }
179 : :
180 : : // kind of a HACK to get locus depending on opening scope resolution
181 : 3481 : location_t locus = UNKNOWN_LOCATION;
182 : 3481 : if (with_opening_scope_resolution)
183 : 0 : locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
184 : : else
185 : 3481 : locus = simple_segments[0].get_locus ();
186 : : // FIXME: this hack probably doesn't actually work
187 : :
188 : 3481 : return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
189 : 3481 : locus);
190 : 3481 : }
191 : :
192 : : void
193 : 252668 : PathInExpression::accept_vis (ASTVisitor &vis)
194 : : {
195 : 252668 : vis.visit (*this);
196 : 252668 : }
197 : :
198 : : std::string
199 : 2 : PathInExpression::as_string () const
200 : : {
201 : 2 : std::string str;
202 : :
203 : 2 : if (has_opening_scope_resolution)
204 : 0 : str = "::";
205 : :
206 : 2 : return str + Path::as_string ();
207 : 2 : }
208 : :
209 : : std::string
210 : 705 : TypePathSegmentGeneric::as_string () const
211 : : {
212 : : // TODO: rewrite to work with non-linearisable types
213 : 2115 : return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
214 : : }
215 : :
216 : : std::string
217 : 0 : TypePathSegmentFunction::as_string () const
218 : : {
219 : : // TODO: rewrite to work with non-linearisable types
220 : 0 : return TypePathSegment::as_string () + function_path.as_string ();
221 : : }
222 : :
223 : : std::string
224 : 82206 : TypePath::as_string () const
225 : : {
226 : : /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
227 : : * literalised */
228 : 82206 : std::string str;
229 : :
230 : 82206 : if (has_opening_scope_resolution)
231 : 31 : str = "::";
232 : :
233 : 164514 : for (const auto &segment : segments)
234 : 246924 : str += segment->as_string () + "::";
235 : :
236 : : // kinda hack - remove last 2 '::' characters
237 : 82206 : str.erase (str.length () - 2);
238 : :
239 : 82206 : return str;
240 : : }
241 : :
242 : : SimplePath
243 : 35 : TypePath::as_simple_path () const
244 : : {
245 : 35 : if (segments.empty ())
246 : 0 : return SimplePath::create_empty ();
247 : :
248 : : // create vector of reserved size (to minimise reallocations)
249 : 35 : std::vector<SimplePathSegment> simple_segments;
250 : 35 : simple_segments.reserve (segments.size ());
251 : :
252 : 70 : for (const auto &segment : segments)
253 : : {
254 : : // return empty path if doesn't meet simple path segment requirements
255 : 35 : if (segment == nullptr || segment->is_error ()
256 : 70 : || !segment->is_ident_only () || segment->as_string () == "Self")
257 : 0 : return SimplePath::create_empty ();
258 : :
259 : : // create segment and add to vector
260 : 35 : std::string segment_str = segment->as_string ();
261 : 70 : simple_segments.push_back (
262 : 70 : SimplePathSegment (std::move (segment_str), segment->get_locus ()));
263 : 35 : }
264 : :
265 : 35 : return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
266 : 35 : locus);
267 : 35 : }
268 : :
269 : : // hopefully definition here will prevent circular dependency issue
270 : : TraitBound *
271 : 0 : TypePath::to_trait_bound (bool in_parens) const
272 : : {
273 : 0 : return new TraitBound (TypePath (*this), get_locus (), in_parens);
274 : : }
275 : :
276 : : std::string
277 : 0 : TypePathFunction::as_string () const
278 : : {
279 : : // TODO: rewrite to work with non-linearisable types
280 : 0 : std::string str ("(");
281 : :
282 : 0 : if (has_inputs ())
283 : : {
284 : : auto i = inputs.begin ();
285 : : auto e = inputs.end ();
286 : :
287 : 0 : for (; i != e; i++)
288 : : {
289 : 0 : str += (*i)->as_string ();
290 : 0 : if (e != i + 1)
291 : 0 : str += ", ";
292 : : }
293 : : }
294 : :
295 : 0 : str += ")";
296 : :
297 : 0 : if (has_return_type ())
298 : 0 : str += " -> " + return_type->as_string ();
299 : :
300 : 0 : return str;
301 : : }
302 : :
303 : : std::string
304 : 0 : QualifiedPathInExpression::as_string () const
305 : : {
306 : 0 : return path_type.as_string () + "::" + Path::as_string ();
307 : : }
308 : :
309 : : std::string
310 : 0 : QualifiedPathInType::as_string () const
311 : : {
312 : : /* TODO: this may need adjusting if segments (e.g. with functions) can't be
313 : : * literalised */
314 : 0 : std::string str = path_type.as_string ();
315 : :
316 : 0 : str += "::" + associated_segment->as_string ();
317 : 0 : for (const auto &segment : segments)
318 : 0 : str += "::" + segment->as_string ();
319 : :
320 : 0 : return str;
321 : : }
322 : :
323 : : void
324 : 712 : ConstGenericParam::accept_vis (ASTVisitor &vis)
325 : : {
326 : 712 : vis.visit (*this);
327 : 712 : }
328 : :
329 : : void
330 : 574022 : TypePathSegment::accept_vis (ASTVisitor &vis)
331 : : {
332 : 574022 : vis.visit (*this);
333 : 574022 : }
334 : :
335 : : void
336 : 32036 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
337 : : {
338 : 32036 : vis.visit (*this);
339 : 32036 : }
340 : :
341 : : void
342 : 331 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
343 : : {
344 : 331 : vis.visit (*this);
345 : 331 : }
346 : :
347 : : void
348 : 623917 : TypePath::accept_vis (ASTVisitor &vis)
349 : : {
350 : 623917 : vis.visit (*this);
351 : 623915 : }
352 : :
353 : : void
354 : 1756 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
355 : : {
356 : 1756 : vis.visit (*this);
357 : 1756 : }
358 : :
359 : : void
360 : 5785 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
361 : : {
362 : 5785 : vis.visit (*this);
363 : 5785 : }
364 : :
365 : : } // namespace AST
366 : : } // namespace Rust
|