Skip to content

Commit f70b5e0

Browse files
committed
desugar: Add desugar dispatch for all desugars
Since we are doing more and more "external" desugars, as in desugars that take a pointer and replace it with another one, rather than modifying it from within, having an external visitor dispatch to the proper desugar helps with code clarity. gcc/rust/ChangeLog: * Make-lang.in: Compile it. * rust-session-manager.cc: Call the expression desugar dispatcher. * ast/rust-desugar-question-mark.cc: Rework class API. * ast/rust-desugar-question-mark.h: Likewise. * ast/rust-expression-yeast.cc: New file. * ast/rust-expression-yeast.h: New file.
1 parent 3a57c56 commit f70b5e0

File tree

6 files changed

+157
-56
lines changed

6 files changed

+157
-56
lines changed

gcc/rust/Make-lang.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,11 @@ GRS_OBJS = \
242242
rust/rust-expand-format-args.o \
243243
rust/rust-lang-item.o \
244244
rust/rust-collect-lang-items.o \
245+
rust/rust-expression-yeast.o \
245246
rust/rust-desugar-for-loops.o \
246247
rust/rust-desugar-question-mark.o \
247248
rust/rust-desugar-apit.o \
249+
# rust/rust-desugar-try-block.o \
248250
$(END)
249251
# removed object files from here
250252

gcc/rust/ast/rust-desugar-question-mark.cc

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,42 +26,12 @@ namespace AST {
2626
DesugarQuestionMark::DesugarQuestionMark () {}
2727

2828
void
29-
DesugarQuestionMark::go (AST::Crate &crate)
29+
DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
3030
{
31-
DesugarQuestionMark::visit (crate);
32-
}
33-
34-
void
35-
DesugarQuestionMark::visit (ExprStmt &stmt)
36-
{
37-
if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
38-
desugar_and_replace (stmt.get_expr_ptr ());
39-
40-
DefaultASTVisitor::visit (stmt);
41-
}
42-
43-
void
44-
DesugarQuestionMark::visit (CallExpr &call)
45-
{
46-
if (call.get_function_expr ().get_expr_kind ()
47-
== Expr::Kind::ErrorPropagation)
48-
desugar_and_replace (call.get_function_expr_ptr ());
49-
50-
for (auto &arg : call.get_params ())
51-
if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
52-
desugar_and_replace (arg);
53-
54-
DefaultASTVisitor::visit (call);
55-
}
56-
57-
void
58-
DesugarQuestionMark::visit (LetStmt &stmt)
59-
{
60-
if (stmt.has_init_expr ()
61-
&& stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
62-
desugar_and_replace (stmt.get_init_expr_ptr ());
31+
auto original = static_cast<ErrorPropagationExpr &> (*ptr);
32+
auto desugared = DesugarQuestionMark ().desugar (original);
6333

64-
DefaultASTVisitor::visit (stmt);
34+
ptr = std::move (desugared);
6535
}
6636

6737
MatchArm
@@ -99,6 +69,12 @@ ok_case (Builder &builder)
9969
MatchCase
10070
err_case (Builder &builder)
10171
{
72+
// TODO: We need to handle the case where there is an enclosing `try {}`
73+
// block, as that will create an additional block label that we can break to.
74+
// This allows try blocks to use the question mark operator without having the
75+
// offending statement early return from the enclosing function
76+
// FIXME: How to mark that there is an enclosing block label?
77+
10278
auto val = builder.identifier_pattern ("err");
10379

10480
auto patterns = std::vector<std::unique_ptr<Pattern>> ();
@@ -154,14 +130,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
154130
expr.get_locus ()));
155131
}
156132

157-
void
158-
DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
159-
{
160-
auto original = static_cast<ErrorPropagationExpr &> (*ptr);
161-
auto desugared = desugar (original);
162-
163-
ptr = std::move (desugared);
164-
}
165-
166133
} // namespace AST
167134
} // namespace Rust

gcc/rust/ast/rust-desugar-question-mark.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
#ifndef RUST_DESUGAR_QUESTION_MARK
2020
#define RUST_DESUGAR_QUESTION_MARK
2121

22-
#include "rust-ast-visitor.h"
2322
#include "rust-expr.h"
24-
#include "rust-stmt.h"
2523

2624
namespace Rust {
2725
namespace AST {
@@ -56,21 +54,15 @@ namespace AST {
5654
// }
5755
// }
5856
// ```
59-
class DesugarQuestionMark : public DefaultASTVisitor
57+
class DesugarQuestionMark
6058
{
61-
using DefaultASTVisitor::visit;
62-
6359
public:
64-
DesugarQuestionMark ();
65-
void go (AST::Crate &);
60+
static void go (std::unique_ptr<Expr> &ptr);
6661

6762
private:
68-
void desugar_and_replace (std::unique_ptr<Expr> &ptr);
69-
std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
63+
DesugarQuestionMark ();
7064

71-
void visit (AST::ExprStmt &) override;
72-
void visit (AST::CallExpr &) override;
73-
void visit (AST::LetStmt &) override;
65+
std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
7466
};
7567

7668
} // namespace AST
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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-expression-yeast.h"
20+
#include "rust-ast-visitor.h"
21+
#include "rust-desugar-question-mark.h"
22+
#include "rust-ast-full.h"
23+
24+
namespace Rust {
25+
namespace AST {
26+
27+
void
28+
ExpressionYeast::go (AST::Crate &crate)
29+
{
30+
DefaultASTVisitor::visit (crate);
31+
}
32+
33+
void
34+
ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
35+
{
36+
switch (expr->get_expr_kind ())
37+
{
38+
// TODO: Handle try-blocks
39+
case Expr::Kind::ErrorPropagation:
40+
DesugarQuestionMark::go (expr);
41+
break;
42+
43+
default:
44+
break;
45+
}
46+
}
47+
48+
void
49+
ExpressionYeast::visit (ExprStmt &stmt)
50+
{
51+
dispatch (stmt.get_expr_ptr ());
52+
53+
DefaultASTVisitor::visit (stmt);
54+
}
55+
56+
void
57+
ExpressionYeast::visit (CallExpr &call)
58+
{
59+
dispatch (call.get_function_expr_ptr ());
60+
61+
for (auto &arg : call.get_params ())
62+
dispatch (arg);
63+
64+
DefaultASTVisitor::visit (call);
65+
}
66+
67+
void
68+
ExpressionYeast::visit (BlockExpr &block)
69+
{
70+
for (auto &stmt : block.get_statements ())
71+
DefaultASTVisitor::visit (stmt);
72+
73+
if (block.has_tail_expr ())
74+
dispatch (block.get_tail_expr_ptr ());
75+
}
76+
77+
void
78+
ExpressionYeast::visit (LetStmt &stmt)
79+
{
80+
if (stmt.has_init_expr ())
81+
dispatch (stmt.get_init_expr_ptr ());
82+
83+
DefaultASTVisitor::visit (stmt);
84+
}
85+
86+
} // namespace AST
87+
} // namespace Rust
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
#ifndef RUST_EXPRESSION_YEAST
20+
#define RUST_EXPRESSION_YEAST
21+
22+
#include "rust-ast-visitor.h"
23+
#include "rust-ast.h"
24+
#include "rust-desugar-question-mark.h"
25+
26+
namespace Rust {
27+
namespace AST {
28+
29+
// This visitor takes care of all the expression desugars: try-blocks,
30+
// error-propagation, etc.
31+
class ExpressionYeast : public AST::DefaultASTVisitor
32+
{
33+
using AST::DefaultASTVisitor::visit;
34+
35+
public:
36+
void go (AST::Crate &);
37+
38+
private:
39+
// Dispatch to the proper desugar
40+
void dispatch (std::unique_ptr<Expr> &expr);
41+
42+
void visit (AST::ExprStmt &) override;
43+
void visit (AST::CallExpr &) override;
44+
void visit (AST::LetStmt &) override;
45+
void visit (AST::BlockExpr &) override;
46+
};
47+
48+
} // namespace AST
49+
} // namespace Rust
50+
51+
#endif // ! RUST_EXPRESSION_YEAST

gcc/rust/rust-session-manager.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "rust-desugar-question-mark.h"
2323
#include "rust-desugar-apit.h"
2424
#include "rust-diagnostics.h"
25+
#include "rust-expression-yeast.h"
2526
#include "rust-hir-pattern-analysis.h"
2627
#include "rust-immutable-name-resolution-context.h"
2728
#include "rust-unsafe-checker.h"
@@ -985,8 +986,9 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx)
985986
// handle AST desugaring
986987
if (!saw_errors ())
987988
{
989+
AST::ExpressionYeast ().go (crate);
990+
988991
AST::DesugarForLoops ().go (crate);
989-
AST::DesugarQuestionMark ().go (crate);
990992
AST::DesugarApit ().go (crate);
991993

992994
// HACK: we may need a final TopLevel pass

0 commit comments

Comments
 (0)