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