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 : #ifndef RUST_DESUGAR_FOR_LOOPS_H
20 : #define RUST_DESUGAR_FOR_LOOPS_H
21 :
22 : #include "rust-ast-builder.h"
23 : #include "rust-expr.h"
24 :
25 : namespace Rust {
26 : namespace AST {
27 :
28 : // Desugar for-loops into a set of other AST nodes. The desugar is of the
29 : // following form:
30 : //
31 : // ```
32 : // for <pat> in <head> <body>
33 : // ```
34 : //
35 : // becomes:
36 : //
37 : // ```
38 : // {
39 : // let result = match ::std::iter::IntoIterator::into_iter(<head>) {
40 : // mut iter => {
41 : // loop {
42 : // let mut __next;
43 : // match ::std::iter::Iterator::next(&mut iter) {
44 : // ::std::option::Option::Some(val) => __next = val,
45 : // ::std::option::Option::None => break
46 : // };
47 : // let <pat> = __next;
48 : //
49 : // <body>;
50 : // }
51 : // }
52 : // };
53 : // result
54 : // }
55 : // ```
56 : //
57 : // NOTE: In a perfect world, this would be an immutable visitor which would take
58 : // ownership of the AST node and return a new one, instead of mutating this one
59 : // in place. Nevertheless, this isn't Rust, and doing immutable visitors in C++
60 : // sucks, and the world isn't perfect, so we are impure and sad.
61 : //
62 : // NOTE: This class could eventually be removed in favor of
63 : // an HIR desugar. This would avoid mutating the AST and would be cleaner.
64 : // However, it requires multiple changes in the way we do typechecking and name
65 : // resolution, as this desugar creates new bindings. Because of this, these new
66 : // bindings need to be inserted into the name-resolution context outside of the
67 : // name resolution pass, which is difficult. Those bindings are needed because
68 : // of the way the typechecker is currently structured, where it will fetch name
69 : // resolution information in order to typecheck paths - which technically isn't
70 : // necessary.
71 : class DesugarForLoops
72 : {
73 : public:
74 : static void go (std::unique_ptr<Expr> &ptr);
75 :
76 : private:
77 : DesugarForLoops ();
78 :
79 : struct DesugarCtx
80 : {
81 16 : DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
82 :
83 : Builder builder;
84 : location_t loc;
85 :
86 : MatchCase make_break_arm ();
87 : MatchCase make_continue_arm ();
88 :
89 : constexpr static const char *continue_pattern_id = "#val";
90 : constexpr static const char *next_value_id = "#__next";
91 : constexpr static const char *iter_id = "#iter";
92 : constexpr static const char *result_id = "#result";
93 : };
94 :
95 : std::unique_ptr<Expr> desugar (ForLoopExpr &expr);
96 : };
97 :
98 : } // namespace AST
99 : } // namespace Rust
100 :
101 : #endif // ! RUST_DESUGAR_FOR_LOOPS_H
|