Branch data Line data Source code
1 : : // Copyright (C) 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 : : #include "rust-desugar-apit.h"
20 : : #include "rust-ast.h"
21 : : #include "rust-type.h"
22 : :
23 : : namespace Rust {
24 : : namespace AST {
25 : :
26 : 31722 : class DesugarApitType : public DefaultASTVisitor
27 : : {
28 : : using DefaultASTVisitor::visit;
29 : :
30 : : public:
31 : : static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>>
32 : 15861 : Desugar (AST::Type &type)
33 : : {
34 : 15861 : DesugarApitType visitor (&type);
35 : 15861 : type.accept_vis (visitor);
36 : 15861 : rust_assert (visitor.translated != nullptr);
37 : 15861 : return std::make_pair (visitor.translated,
38 : 15861 : std::move (visitor.implicit_generic_params));
39 : 15861 : }
40 : :
41 : : // Generate a unique impl trait parameter name
42 : 102 : static Identifier get_impl_name ()
43 : : {
44 : 102 : static size_t counter = 0;
45 : 204 : return Identifier ("Impl_" + std::to_string (counter++));
46 : : }
47 : :
48 : : // these can hold other types
49 : 47 : void visit (AST::TupleType &tuple) override
50 : : {
51 : 131 : for (auto &elem : tuple.get_elems ())
52 : : {
53 : 84 : auto &type = *elem.get ();
54 : 84 : auto desugar = Desugar (type);
55 : 84 : auto tt = desugar.first;
56 : :
57 : 84 : auto &implicit_generics = desugar.second;
58 : 84 : if (implicit_generics.empty ())
59 : 70 : continue;
60 : :
61 : 14 : if (tt != elem.get ())
62 : 14 : elem = std::unique_ptr<Type> (tt);
63 : :
64 : 28 : for (auto &implicit_generic : implicit_generics)
65 : 14 : implicit_generic_params.push_back (std::move (implicit_generic));
66 : 84 : }
67 : 47 : }
68 : :
69 : 343 : void visit (AST::ArrayType &type) override
70 : : {
71 : 343 : auto &element_type = type.get_element_type ();
72 : 343 : auto desugar = Desugar (*element_type);
73 : 343 : auto tt = desugar.first;
74 : :
75 : 343 : auto &implicit_generics = desugar.second;
76 : 343 : if (implicit_generics.empty ())
77 : 343 : return;
78 : :
79 : 0 : if (tt != element_type.get ())
80 : 0 : element_type = std::unique_ptr<AST::Type> (tt);
81 : :
82 : 0 : for (auto &implicit_generic : implicit_generics)
83 : 0 : implicit_generic_params.push_back (std::move (implicit_generic));
84 : 343 : }
85 : :
86 : 2950 : void visit (AST::ReferenceType &type) override
87 : : {
88 : : // Get a reference to the current type for in-place modification
89 : 2950 : auto &referenced_type = type.get_type_referenced ();
90 : 2950 : auto desugar = Desugar (referenced_type);
91 : 2950 : auto tt = desugar.first;
92 : :
93 : 2950 : auto &implicit_generics = desugar.second;
94 : 2950 : if (implicit_generics.empty ())
95 : 2936 : return;
96 : :
97 : : // Update the reference type's contents rather than creating a new one
98 : 14 : if (&referenced_type != tt)
99 : : {
100 : 14 : std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
101 : 14 : static_cast<AST::TypeNoBounds *> (tt));
102 : 14 : type.get_type_ptr () = std::move (new_type_no_bounds);
103 : 14 : }
104 : :
105 : : // Collect all the implicit generic parameters we found
106 : 28 : for (auto &implicit_generic : implicit_generics)
107 : 14 : implicit_generic_params.push_back (std::move (implicit_generic));
108 : 2950 : }
109 : :
110 : 1669 : void visit (AST::RawPointerType &type) override
111 : : {
112 : 1669 : auto &pointed_type = type.get_type_pointed_to ();
113 : 1669 : auto desugar = Desugar (pointed_type);
114 : 1669 : auto tt = desugar.first;
115 : :
116 : 1669 : auto &implicit_generics = desugar.second;
117 : 1669 : if (implicit_generics.empty ())
118 : 1669 : return;
119 : :
120 : : // Update the pointer's inner type directly using the new accessor
121 : 0 : if (&pointed_type != tt)
122 : : {
123 : 0 : std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
124 : 0 : static_cast<AST::TypeNoBounds *> (tt));
125 : 0 : type.get_type_ptr () = std::move (new_type_no_bounds);
126 : 0 : }
127 : :
128 : : // Collect all the implicit generic parameters we found
129 : 0 : for (auto &implicit_generic : implicit_generics)
130 : 0 : implicit_generic_params.push_back (std::move (implicit_generic));
131 : 1669 : }
132 : :
133 : 228 : void visit (AST::SliceType &type) override
134 : : {
135 : 228 : auto &element_type = type.get_elem_type ();
136 : 228 : auto desugar = Desugar (element_type);
137 : 228 : auto tt = desugar.first;
138 : :
139 : 228 : auto &implicit_generics = desugar.second;
140 : 228 : if (implicit_generics.empty ())
141 : 228 : return;
142 : :
143 : 0 : if (&element_type != tt)
144 : : {
145 : 0 : std::unique_ptr<AST::Type> new_elem_type (tt);
146 : 0 : type.get_elem_type_ptr () = std::move (new_elem_type);
147 : 0 : }
148 : :
149 : : // Collect all the implicit generic parameters we found
150 : 0 : for (auto &implicit_generic : implicit_generics)
151 : 0 : implicit_generic_params.push_back (std::move (implicit_generic));
152 : 228 : }
153 : :
154 : 2 : void visit (AST::ParenthesisedType &type) override
155 : : {
156 : 2 : auto &inner_type_ptr = type.get_type_in_parens ();
157 : 2 : auto desugar = Desugar (*inner_type_ptr);
158 : 2 : auto tt = desugar.first;
159 : :
160 : 2 : auto &implicit_generics = desugar.second;
161 : 2 : if (implicit_generics.empty ())
162 : 2 : return;
163 : :
164 : 0 : if (inner_type_ptr.get () != tt)
165 : : {
166 : 0 : std::unique_ptr<AST::Type> new_inner_type (tt);
167 : 0 : inner_type_ptr = std::move (new_inner_type);
168 : 0 : }
169 : :
170 : : // Collect all the implicit generic parameters we found
171 : 0 : for (auto &implicit_generic : implicit_generics)
172 : 0 : implicit_generic_params.push_back (std::move (implicit_generic));
173 : 2 : }
174 : :
175 : : // this is where the desugar happens
176 : 0 : void visit (AST::ImplTraitType &type) override
177 : : {
178 : : // Generate a unique name using the static method
179 : 0 : auto ident = get_impl_name ();
180 : :
181 : : // Create a type path for the new generic parameter
182 : : // Create a SimplePathSegment with the identifier string
183 : 0 : auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
184 : : // Create a vector of SimplePathSegments for SimplePath constructor
185 : 0 : std::vector<SimplePathSegment> simple_segs = {simple_seg};
186 : : // Create a SimplePath
187 : 0 : auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
188 : :
189 : : // Convert to TypePath by creating path segments
190 : 0 : std::vector<std::unique_ptr<TypePathSegment>> segments;
191 : 0 : segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
192 : 0 : PathIdentSegment (ident.as_string (), type.get_locus ()), false,
193 : 0 : type.get_locus ())));
194 : :
195 : : // Create TypePath from segments
196 : 0 : auto type_path
197 : 0 : = new TypePath (std::move (segments), type.get_locus (), false);
198 : :
199 : : // Convert bounds from impl trait to generic parameter bounds
200 : 0 : std::vector<std::unique_ptr<TypeParamBound>> bounds;
201 : 0 : for (auto &bound : type.get_type_param_bounds ())
202 : 0 : bounds.push_back (bound->clone_type_param_bound ());
203 : :
204 : : // Create the new generic parameter
205 : 0 : auto generic_param = std::unique_ptr<TypeParam> (
206 : : new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
207 : 0 : true /*from impl trait*/));
208 : :
209 : : // Store the generic parameter to be added to the function signature
210 : 0 : implicit_generic_params.push_back (std::move (generic_param));
211 : :
212 : : // Replace impl trait with the new type parameter
213 : 0 : translated = type_path;
214 : 0 : }
215 : :
216 : 102 : void visit (AST::ImplTraitTypeOneBound &type) override
217 : : {
218 : : // Generate a unique name using the static method
219 : 102 : auto ident = get_impl_name ();
220 : :
221 : : // Create a type path for the new generic parameter
222 : : // Create a SimplePathSegment with the identifier string
223 : 204 : auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
224 : : // Create a vector of SimplePathSegments for SimplePath constructor
225 : 204 : std::vector<SimplePathSegment> simple_segs = {simple_seg};
226 : : // Create a SimplePath
227 : 102 : auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
228 : :
229 : : // Convert to TypePath by creating path segments
230 : 102 : std::vector<std::unique_ptr<TypePathSegment>> segments;
231 : 102 : segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
232 : 306 : PathIdentSegment (ident.as_string (), type.get_locus ()), false,
233 : 204 : type.get_locus ())));
234 : :
235 : : // Create TypePath from segments
236 : 102 : auto type_path
237 : 102 : = new TypePath (std::move (segments), type.get_locus (), false);
238 : :
239 : : // Convert the bound to a generic parameter bound
240 : 102 : std::vector<std::unique_ptr<TypeParamBound>> bounds;
241 : 102 : bounds.push_back (std::move (type.get_trait_bound ()));
242 : :
243 : : // Create the new generic parameter
244 : 102 : auto generic_param = std::unique_ptr<TypeParam> (
245 : : new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
246 : 102 : true /*from impl trait*/));
247 : :
248 : : // Store the generic parameter to be added to the function signature
249 : 102 : implicit_generic_params.push_back (std::move (generic_param));
250 : :
251 : : // Replace impl trait with the new type parameter
252 : 102 : translated = type_path;
253 : 102 : }
254 : :
255 : : private:
256 : 15861 : DesugarApitType (AST::Type *base)
257 : 15861 : : translated (base), implicit_generic_params ()
258 : : {}
259 : :
260 : : AST::Type *translated;
261 : : std::vector<std::unique_ptr<GenericParam>> implicit_generic_params;
262 : : };
263 : :
264 : : // ---------
265 : :
266 : 168 : class ApitBoundProcessor
267 : : {
268 : : public:
269 : 84 : ApitBoundProcessor (
270 : : WhereClause &where_clause,
271 : : std::vector<std::unique_ptr<GenericParam>> &generic_params)
272 : 84 : : where_clause (where_clause), generic_params (generic_params)
273 : : {}
274 : :
275 : 84 : void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics)
276 : : {
277 : : // some desugars are more complex so imagine this case
278 : : //
279 : : // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 {
280 : : // 15
281 : : // }
282 : : //
283 : : // this needs to become:
284 : : //
285 : : // pub fn foo<T, U>(_value: T) -> i32
286 : : // where
287 : : // T: Bar<Baz = U>,
288 : : // U: Foo,
289 : : // {
290 : : // 15
291 : : // }
292 : : //
293 : : // so we need to walk all the implicit generics and the trait bounds paths
294 : : // for more generics
295 : :
296 : 175 : for (auto &implicit_generic : implicit_generics)
297 : : {
298 : 91 : switch (implicit_generic->get_kind ())
299 : : {
300 : 91 : case GenericParam::Kind::Type:
301 : 91 : {
302 : 91 : TypeParam &p
303 : 91 : = *static_cast<TypeParam *> (implicit_generic.get ());
304 : :
305 : 91 : process_type_param (p);
306 : 91 : generic_params.push_back (std::move (implicit_generic));
307 : 102 : for (auto &synth : synthetic_params)
308 : 11 : generic_params.push_back (std::move (synth));
309 : 91 : synthetic_params.clear ();
310 : : }
311 : 91 : break;
312 : :
313 : 0 : default:
314 : 0 : generic_params.push_back (std::move (implicit_generic));
315 : 0 : break;
316 : : }
317 : : }
318 : 84 : }
319 : :
320 : : private:
321 : 91 : void process_type_param (TypeParam &p)
322 : : {
323 : 91 : auto &bounds = p.get_type_param_bounds ();
324 : 91 : std::vector<size_t> bounds_to_remove;
325 : 182 : for (size_t i = 0; i < bounds.size (); i++)
326 : : {
327 : 91 : auto &tb = bounds[i];
328 : 91 : switch (tb->get_bound_type ())
329 : : {
330 : 91 : case TypeParamBound::TypeParamBoundType::TRAIT:
331 : 91 : {
332 : 91 : TraitBound &ttb = *static_cast<TraitBound *> (tb.get ());
333 : 91 : TypePath &path = ttb.get_type_path ();
334 : 91 : bool deusgared = process_type_path (p, ttb, path);
335 : 91 : if (deusgared)
336 : 11 : bounds_to_remove.push_back (i);
337 : : }
338 : :
339 : 91 : default:
340 : 91 : break;
341 : : }
342 : : }
343 : 102 : for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend ();
344 : 11 : ++it)
345 : 11 : bounds.erase (bounds.begin () + *it);
346 : 91 : }
347 : :
348 : 91 : bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path)
349 : : {
350 : 91 : bool desugared = false;
351 : 182 : for (auto &segment : path.get_segments ())
352 : : {
353 : 91 : switch (segment->get_type ())
354 : : {
355 : 11 : case TypePathSegment::SegmentType::GENERIC:
356 : 11 : {
357 : 11 : TypePathSegmentGeneric &seg
358 : 11 : = *static_cast<TypePathSegmentGeneric *> (segment.get ());
359 : 11 : desugared |= process_generic_segment (p, parent, path, seg);
360 : : }
361 : :
362 : 91 : default:
363 : 91 : break;
364 : : }
365 : : }
366 : 91 : return desugared;
367 : : }
368 : :
369 : 11 : bool process_generic_segment (TypeParam &p, TraitBound &parent,
370 : : TypePath &path, TypePathSegmentGeneric &seg)
371 : : {
372 : : // we need to look for any impl types as default arguments in any generics
373 : : // and remove this index from the generic arguments by using a where
374 : : // constraint instead
375 : :
376 : 11 : std::vector<std::unique_ptr<WhereClauseItem>> new_clauses;
377 : 11 : GenericArgs &generic_args = seg.get_generic_args ();
378 : 11 : std::vector<std::reference_wrapper<const GenericArgsBinding>>
379 : 11 : bindings_desugared;
380 : 11 : std::vector<GenericArgsBinding> &bindings
381 : 11 : = generic_args.get_binding_args ();
382 : :
383 : 22 : for (auto &generic : bindings)
384 : : {
385 : 11 : auto &t = generic.get_type ();
386 : 11 : auto translated = DesugarApitType::Desugar (t);
387 : 11 : auto tt = translated.first;
388 : :
389 : 11 : auto &implicit_generics = translated.second;
390 : 11 : if (implicit_generics.empty ())
391 : 0 : continue;
392 : :
393 : 11 : if (tt != &t)
394 : : {
395 : 11 : bindings_desugared.push_back (generic);
396 : 11 : generic.get_type_ptr () = std::unique_ptr<Type> (tt);
397 : : }
398 : :
399 : 22 : for (auto &implicit_generic : implicit_generics)
400 : : {
401 : 11 : switch (implicit_generic->get_kind ())
402 : : {
403 : 11 : case GenericParam::Kind::Type:
404 : 11 : {
405 : 11 : TypeParam &tp
406 : 11 : = *static_cast<TypeParam *> (implicit_generic.get ());
407 : :
408 : 11 : std::vector<std::unique_ptr<TypeParamBound>>
409 : 11 : type_param_bounds;
410 : 22 : for (auto &b : tp.get_type_param_bounds ())
411 : 11 : type_param_bounds.push_back (std::move (b));
412 : 11 : tp.get_type_param_bounds ().clear ();
413 : :
414 : : // add synthetic parameter for this
415 : 11 : synthetic_params.push_back (std::move (implicit_generic));
416 : :
417 : 11 : auto bound_type_path
418 : 11 : = get_type_for_identifier (tp.get_type_representation ());
419 : :
420 : 11 : auto clause = new TypeBoundWhereClauseItem (
421 : : {}, std::move (bound_type_path),
422 : 11 : std::move (type_param_bounds), tp.get_locus ());
423 : 11 : std::unique_ptr<WhereClauseItem> clause_item
424 : 11 : = std::unique_ptr<WhereClauseItem> (clause);
425 : 11 : new_clauses.push_back (std::move (clause_item));
426 : 11 : }
427 : 11 : break;
428 : :
429 : 0 : default:
430 : 0 : synthetic_params.push_back (std::move (implicit_generic));
431 : 0 : break;
432 : : }
433 : : }
434 : 11 : }
435 : :
436 : 22 : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
437 : 22 : auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent));
438 : 11 : type_param_bounds.push_back (std::move (bound));
439 : 11 : auto parent_type_path
440 : 22 : = get_type_for_identifier (p.get_type_representation ());
441 : 11 : auto clause
442 : : = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path),
443 : : std::move (type_param_bounds),
444 : 11 : parent.get_locus ());
445 : 11 : std::unique_ptr<WhereClauseItem> clause_item
446 : 11 : = std::unique_ptr<WhereClauseItem> (clause);
447 : 11 : where_clause.get_items ().push_back (std::move (clause_item));
448 : :
449 : 22 : for (auto &where_item : new_clauses)
450 : 11 : where_clause.get_items ().push_back (std::move (where_item));
451 : :
452 : 11 : return !bindings_desugared.empty ();
453 : 11 : }
454 : :
455 : 22 : static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident)
456 : : {
457 : 22 : auto simple_seg
458 : 44 : = SimplePathSegment (ident.as_string (), ident.get_locus ());
459 : 44 : std::vector<SimplePathSegment> simple_segs = {simple_seg};
460 : 22 : auto simple_path = SimplePath (simple_segs, false, ident.get_locus ());
461 : 22 : std::vector<std::unique_ptr<TypePathSegment>> segments;
462 : 22 : segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
463 : 66 : PathIdentSegment (ident.as_string (), ident.get_locus ()), false,
464 : 44 : ident.get_locus ())));
465 : 22 : auto type_path = new TypePath (std::move (segments), ident.get_locus ());
466 : 22 : return std::unique_ptr<Type> (type_path);
467 : 22 : }
468 : :
469 : : private:
470 : : WhereClause &where_clause;
471 : : std::vector<std::unique_ptr<GenericParam>> &generic_params;
472 : :
473 : : // mutates
474 : : std::vector<std::unique_ptr<GenericParam>> synthetic_params;
475 : : };
476 : :
477 : : // ---------
478 : :
479 : 4208 : DesugarApit::DesugarApit () {}
480 : :
481 : : void
482 : 4208 : DesugarApit::go (AST::Crate &crate)
483 : : {
484 : 4208 : DefaultASTVisitor::visit (crate);
485 : 4208 : }
486 : :
487 : : void
488 : 17738 : DesugarApit::visit (AST::Function &function)
489 : : {
490 : 17738 : if (!function.has_function_params ())
491 : : return;
492 : :
493 : : auto &fn_params = function.get_function_params ();
494 : 31849 : for (auto ¶m : fn_params)
495 : : {
496 : 19382 : if (param->is_variadic () || param->is_self ())
497 : 19298 : continue;
498 : :
499 : 10574 : auto *p = param.get ();
500 : 10574 : auto &fp = *static_cast<AST::FunctionParam *> (p);
501 : 10574 : auto &type = fp.get_type ();
502 : :
503 : 10574 : auto translated = DesugarApitType::Desugar (type);
504 : 10574 : auto tt = translated.first;
505 : :
506 : 10574 : auto &implicit_generics = translated.second;
507 : 10574 : if (implicit_generics.empty ())
508 : 10490 : continue;
509 : :
510 : 84 : if (fp.get_type_ptr ().get () != tt)
511 : : {
512 : 63 : fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt);
513 : : }
514 : :
515 : 84 : ApitBoundProcessor processor (function.get_where_clause (),
516 : 84 : function.get_generic_params ());
517 : 84 : processor.go (implicit_generics);
518 : 10574 : }
519 : : }
520 : :
521 : : } // namespace AST
522 : : } // namespace Rust
|