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 73070 : 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 36535 : Desugar (AST::Type &type)
34 : {
35 36535 : DesugarApitType visitor (&type);
36 36535 : type.accept_vis (visitor);
37 36535 : rust_assert (visitor.translated != nullptr);
38 36535 : return std::make_pair (visitor.translated,
39 36535 : std::move (visitor.implicit_generic_params));
40 36535 : }
41 :
42 : // Generate a unique impl trait parameter name
43 167 : static Identifier get_impl_name ()
44 : {
45 167 : static size_t counter = 0;
46 334 : return Identifier ("Impl_" + std::to_string (counter++));
47 : }
48 :
49 : // these can hold other types
50 204 : void visit (AST::TupleType &tuple) override
51 : {
52 988 : for (auto &elem : tuple.get_elems ())
53 : {
54 784 : auto &type = *elem.get ();
55 784 : auto desugar = Desugar (type);
56 784 : auto tt = desugar.first;
57 :
58 784 : auto &implicit_generics = desugar.second;
59 784 : if (implicit_generics.empty ())
60 770 : 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 784 : }
68 204 : }
69 :
70 452 : void visit (AST::ArrayType &type) override
71 : {
72 452 : auto &element_type = type.get_element_type ();
73 452 : auto desugar = Desugar (*element_type);
74 452 : auto tt = desugar.first;
75 :
76 452 : auto &implicit_generics = desugar.second;
77 452 : if (implicit_generics.empty ())
78 452 : 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 452 : }
86 :
87 6775 : void visit (AST::ReferenceType &type) override
88 : {
89 : // Get a reference to the current type for in-place modification
90 6775 : auto &referenced_type = type.get_type_referenced ();
91 6775 : auto desugar = Desugar (referenced_type);
92 6775 : auto tt = desugar.first;
93 :
94 6775 : auto &implicit_generics = desugar.second;
95 6775 : if (implicit_generics.empty ())
96 6745 : 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 6775 : }
110 :
111 2280 : void visit (AST::RawPointerType &type) override
112 : {
113 2280 : auto &pointed_type = type.get_type_pointed_to ();
114 2280 : auto desugar = Desugar (pointed_type);
115 2280 : auto tt = desugar.first;
116 :
117 2280 : auto &implicit_generics = desugar.second;
118 2280 : if (implicit_generics.empty ())
119 2280 : 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 2280 : }
133 :
134 457 : void visit (AST::SliceType &type) override
135 : {
136 457 : auto &element_type = type.get_elem_type ();
137 457 : auto desugar = Desugar (element_type);
138 457 : auto tt = desugar.first;
139 :
140 457 : auto &implicit_generics = desugar.second;
141 457 : if (implicit_generics.empty ())
142 457 : 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 457 : }
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 167 : void visit (AST::ImplTraitTypeOneBound &type) override
221 : {
222 : // Generate a unique name using the static method
223 167 : 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 334 : auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
228 : // Create a vector of SimplePathSegments for SimplePath constructor
229 334 : std::vector<SimplePathSegment> simple_segs = {simple_seg};
230 : // Create a SimplePath
231 167 : auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
232 :
233 : // Convert to TypePath by creating path segments
234 167 : std::vector<std::unique_ptr<TypePathSegment>> segments;
235 167 : segments.emplace_back (
236 334 : new TypePathSegment (PathIdentSegment (ident.as_string (),
237 334 : type.get_locus ()),
238 334 : false, type.get_locus ()));
239 :
240 : // Create TypePath from segments
241 167 : auto type_path
242 167 : = new TypePath (std::move (segments), type.get_locus (), false);
243 :
244 : // Convert the bound to a generic parameter bound
245 167 : std::vector<std::unique_ptr<TypeParamBound>> bounds;
246 167 : bounds.push_back (std::move (type.get_trait_bound ()));
247 :
248 : // Create the new generic parameter
249 167 : auto generic_param = std::unique_ptr<TypeParam> (
250 : new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
251 167 : true /*from impl trait*/));
252 :
253 : // Store the generic parameter to be added to the function signature
254 167 : implicit_generic_params.push_back (std::move (generic_param));
255 :
256 : // Replace impl trait with the new type parameter
257 167 : translated = type_path;
258 167 : }
259 :
260 : private:
261 36535 : DesugarApitType (AST::Type *base)
262 36535 : : 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 298 : class ApitBoundProcessor
272 : {
273 : public:
274 149 : ApitBoundProcessor (
275 : WhereClause &where_clause,
276 : std::vector<std::unique_ptr<GenericParam>> &generic_params)
277 149 : : where_clause (where_clause), generic_params (generic_params)
278 : {}
279 :
280 149 : 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 305 : for (auto &implicit_generic : implicit_generics)
302 : {
303 156 : switch (implicit_generic->get_kind ())
304 : {
305 156 : case GenericParam::Kind::Type:
306 156 : {
307 156 : TypeParam &p
308 156 : = *static_cast<TypeParam *> (implicit_generic.get ());
309 :
310 156 : process_type_param (p);
311 156 : generic_params.push_back (std::move (implicit_generic));
312 167 : for (auto &synth : synthetic_params)
313 11 : generic_params.push_back (std::move (synth));
314 156 : synthetic_params.clear ();
315 : }
316 156 : break;
317 :
318 0 : default:
319 0 : generic_params.push_back (std::move (implicit_generic));
320 0 : break;
321 : }
322 : }
323 149 : }
324 :
325 : private:
326 156 : void process_type_param (TypeParam &p)
327 : {
328 156 : auto &bounds = p.get_type_param_bounds ();
329 156 : std::vector<size_t> bounds_to_remove;
330 312 : for (size_t i = 0; i < bounds.size (); i++)
331 : {
332 156 : auto &tb = bounds[i];
333 156 : switch (tb->get_bound_type ())
334 : {
335 156 : case TypeParamBound::TypeParamBoundType::TRAIT:
336 156 : {
337 156 : TraitBound &ttb = *static_cast<TraitBound *> (tb.get ());
338 156 : TypePath &path = ttb.get_type_path ();
339 156 : bool deusgared = process_type_path (p, ttb, path);
340 156 : if (deusgared)
341 11 : bounds_to_remove.push_back (i);
342 : }
343 :
344 156 : default:
345 156 : break;
346 : }
347 : }
348 167 : for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend ();
349 11 : ++it)
350 11 : bounds.erase (bounds.begin () + *it);
351 156 : }
352 :
353 156 : bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path)
354 : {
355 156 : bool desugared = false;
356 312 : for (auto &segment : path.get_segments ())
357 : {
358 156 : switch (segment->get_type ())
359 : {
360 13 : case TypePathSegment::SegmentType::GENERIC:
361 13 : {
362 13 : TypePathSegmentGeneric &seg
363 13 : = *static_cast<TypePathSegmentGeneric *> (segment.get ());
364 13 : desugared |= process_generic_segment (p, parent, path, seg);
365 : }
366 :
367 156 : default:
368 156 : break;
369 : }
370 : }
371 156 : return desugared;
372 : }
373 :
374 13 : 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 13 : std::vector<std::unique_ptr<WhereClauseItem>> new_clauses;
382 13 : GenericArgs &generic_args = seg.get_generic_args ();
383 13 : std::vector<std::reference_wrapper<const GenericArgsBinding>>
384 13 : bindings_desugared;
385 13 : std::vector<GenericArgsBinding> &bindings
386 13 : = generic_args.get_binding_args ();
387 :
388 24 : for (auto &generic : bindings)
389 : {
390 11 : auto &t = generic.get_type ();
391 11 : auto translated = DesugarApitType::Desugar (t);
392 11 : auto tt = translated.first;
393 :
394 11 : auto &implicit_generics = translated.second;
395 11 : if (implicit_generics.empty ())
396 0 : 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 11 : }
443 :
444 13 : std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
445 26 : auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent));
446 13 : type_param_bounds.push_back (std::move (bound));
447 13 : auto parent_type_path
448 26 : = get_type_for_identifier (p.get_type_representation ());
449 13 : auto clause
450 : = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path),
451 : std::move (type_param_bounds),
452 13 : parent.get_locus ());
453 13 : std::unique_ptr<WhereClauseItem> clause_item
454 13 : = std::unique_ptr<WhereClauseItem> (clause);
455 13 : where_clause.get_items ().push_back (std::move (clause_item));
456 :
457 24 : for (auto &where_item : new_clauses)
458 11 : where_clause.get_items ().push_back (std::move (where_item));
459 :
460 13 : return !bindings_desugared.empty ();
461 13 : }
462 :
463 24 : static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident)
464 : {
465 24 : auto simple_seg
466 48 : = SimplePathSegment (ident.as_string (), ident.get_locus ());
467 48 : std::vector<SimplePathSegment> simple_segs = {simple_seg};
468 24 : auto simple_path = SimplePath (simple_segs, false, ident.get_locus ());
469 24 : std::vector<std::unique_ptr<TypePathSegment>> segments;
470 24 : segments.emplace_back (
471 72 : new TypePathSegment (PathIdentSegment (ident.as_string (),
472 48 : ident.get_locus ()),
473 48 : false, ident.get_locus ()));
474 24 : auto type_path = new TypePath (std::move (segments), ident.get_locus ());
475 24 : return std::unique_ptr<Type> (type_path);
476 24 : }
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 4797 : DesugarApit::DesugarApit () {}
489 :
490 : void
491 4797 : DesugarApit::go (AST::Crate &crate)
492 : {
493 4797 : DefaultASTVisitor::visit (crate);
494 4797 : }
495 :
496 : void
497 31381 : DesugarApit::visit (AST::Function &function)
498 : {
499 31381 : if (!function.has_function_params ())
500 : return;
501 :
502 : auto &fn_params = function.get_function_params ();
503 68130 : for (auto ¶m : fn_params)
504 : {
505 43053 : if (param->is_variadic () || param->is_self ())
506 42904 : continue;
507 :
508 25772 : auto *p = param.get ();
509 25772 : auto &fp = *static_cast<AST::FunctionParam *> (p);
510 25772 : auto &type = fp.get_type ();
511 :
512 25772 : auto translated = DesugarApitType::Desugar (type);
513 25772 : auto tt = translated.first;
514 :
515 25772 : auto &implicit_generics = translated.second;
516 25772 : if (implicit_generics.empty ())
517 25623 : continue;
518 :
519 149 : if (fp.get_type_ptr ().get () != tt)
520 : {
521 112 : fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt);
522 : }
523 :
524 149 : ApitBoundProcessor processor (function.get_where_clause (),
525 149 : function.get_generic_params ());
526 149 : processor.go (implicit_generics);
527 25772 : }
528 :
529 25077 : DefaultASTVisitor::visit (function);
530 : }
531 :
532 : } // namespace AST
533 : } // namespace Rust
|