https://gcc.gnu.org/g:5594047290c1499fd468ec74a8d7759ecd853f91

commit r16-2954-g5594047290c1499fd468ec74a8d7759ecd853f91
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Mon Jul 21 11:27:01 2025 +0200

    gccrs: 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.

Diff:
---
 gcc/rust/Make-lang.in                      |  2 +
 gcc/rust/ast/rust-desugar-question-mark.cc | 53 ++++--------------
 gcc/rust/ast/rust-desugar-question-mark.h  | 16 ++----
 gcc/rust/ast/rust-expression-yeast.cc      | 87 ++++++++++++++++++++++++++++++
 gcc/rust/ast/rust-expression-yeast.h       | 51 ++++++++++++++++++
 gcc/rust/rust-session-manager.cc           |  4 +-
 6 files changed, 157 insertions(+), 56 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index c7846892d895..506435d20038 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -242,9 +242,11 @@ GRS_OBJS = \
        rust/rust-expand-format-args.o \
        rust/rust-lang-item.o \
        rust/rust-collect-lang-items.o \
+       rust/rust-expression-yeast.o \
        rust/rust-desugar-for-loops.o \
        rust/rust-desugar-question-mark.o \
        rust/rust-desugar-apit.o \
+       # rust/rust-desugar-try-block.o \
     $(END)
 # removed object files from here
 
diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc 
b/gcc/rust/ast/rust-desugar-question-mark.cc
index 4d2933b1bee3..ef2bdb87307f 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.cc
+++ b/gcc/rust/ast/rust-desugar-question-mark.cc
@@ -26,42 +26,12 @@ namespace AST {
 DesugarQuestionMark::DesugarQuestionMark () {}
 
 void
-DesugarQuestionMark::go (AST::Crate &crate)
+DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
 {
-  DesugarQuestionMark::visit (crate);
-}
-
-void
-DesugarQuestionMark::visit (ExprStmt &stmt)
-{
-  if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
-    desugar_and_replace (stmt.get_expr_ptr ());
-
-  DefaultASTVisitor::visit (stmt);
-}
-
-void
-DesugarQuestionMark::visit (CallExpr &call)
-{
-  if (call.get_function_expr ().get_expr_kind ()
-      == Expr::Kind::ErrorPropagation)
-    desugar_and_replace (call.get_function_expr_ptr ());
-
-  for (auto &arg : call.get_params ())
-    if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
-      desugar_and_replace (arg);
-
-  DefaultASTVisitor::visit (call);
-}
-
-void
-DesugarQuestionMark::visit (LetStmt &stmt)
-{
-  if (stmt.has_init_expr ()
-      && stmt.get_init_expr ().get_expr_kind () == 
Expr::Kind::ErrorPropagation)
-    desugar_and_replace (stmt.get_init_expr_ptr ());
+  auto original = static_cast<ErrorPropagationExpr &> (*ptr);
+  auto desugared = DesugarQuestionMark ().desugar (original);
 
-  DefaultASTVisitor::visit (stmt);
+  ptr = std::move (desugared);
 }
 
 MatchArm
@@ -99,6 +69,12 @@ ok_case (Builder &builder)
 MatchCase
 err_case (Builder &builder)
 {
+  // TODO: We need to handle the case where there is an enclosing `try {}`
+  // block, as that will create an additional block label that we can break to.
+  // This allows try blocks to use the question mark operator without having 
the
+  // offending statement early return from the enclosing function
+  // FIXME: How to mark that there is an enclosing block label?
+
   auto val = builder.identifier_pattern ("err");
 
   auto patterns = std::vector<std::unique_ptr<Pattern>> ();
@@ -154,14 +130,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
                                                    expr.get_locus ()));
 }
 
-void
-DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
-{
-  auto original = static_cast<ErrorPropagationExpr &> (*ptr);
-  auto desugared = desugar (original);
-
-  ptr = std::move (desugared);
-}
-
 } // namespace AST
 } // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-question-mark.h 
b/gcc/rust/ast/rust-desugar-question-mark.h
index e4c513f461fd..542c52b6310d 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.h
+++ b/gcc/rust/ast/rust-desugar-question-mark.h
@@ -19,9 +19,7 @@
 #ifndef RUST_DESUGAR_QUESTION_MARK
 #define RUST_DESUGAR_QUESTION_MARK
 
-#include "rust-ast-visitor.h"
 #include "rust-expr.h"
-#include "rust-stmt.h"
 
 namespace Rust {
 namespace AST {
@@ -56,21 +54,15 @@ namespace AST {
 //   }
 // }
 // ```
-class DesugarQuestionMark : public DefaultASTVisitor
+class DesugarQuestionMark
 {
-  using DefaultASTVisitor::visit;
-
 public:
-  DesugarQuestionMark ();
-  void go (AST::Crate &);
+  static void go (std::unique_ptr<Expr> &ptr);
 
 private:
-  void desugar_and_replace (std::unique_ptr<Expr> &ptr);
-  std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
+  DesugarQuestionMark ();
 
-  void visit (AST::ExprStmt &) override;
-  void visit (AST::CallExpr &) override;
-  void visit (AST::LetStmt &) override;
+  std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
 };
 
 } // namespace AST
diff --git a/gcc/rust/ast/rust-expression-yeast.cc 
b/gcc/rust/ast/rust-expression-yeast.cc
new file mode 100644
index 000000000000..1089b71034c2
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.cc
@@ -0,0 +1,87 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-expression-yeast.h"
+#include "rust-ast-visitor.h"
+#include "rust-desugar-question-mark.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+namespace AST {
+
+void
+ExpressionYeast::go (AST::Crate &crate)
+{
+  DefaultASTVisitor::visit (crate);
+}
+
+void
+ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
+{
+  switch (expr->get_expr_kind ())
+    {
+      // TODO: Handle try-blocks
+    case Expr::Kind::ErrorPropagation:
+      DesugarQuestionMark::go (expr);
+      break;
+
+    default:
+      break;
+    }
+}
+
+void
+ExpressionYeast::visit (ExprStmt &stmt)
+{
+  dispatch (stmt.get_expr_ptr ());
+
+  DefaultASTVisitor::visit (stmt);
+}
+
+void
+ExpressionYeast::visit (CallExpr &call)
+{
+  dispatch (call.get_function_expr_ptr ());
+
+  for (auto &arg : call.get_params ())
+    dispatch (arg);
+
+  DefaultASTVisitor::visit (call);
+}
+
+void
+ExpressionYeast::visit (BlockExpr &block)
+{
+  for (auto &stmt : block.get_statements ())
+    DefaultASTVisitor::visit (stmt);
+
+  if (block.has_tail_expr ())
+    dispatch (block.get_tail_expr_ptr ());
+}
+
+void
+ExpressionYeast::visit (LetStmt &stmt)
+{
+  if (stmt.has_init_expr ())
+    dispatch (stmt.get_init_expr_ptr ());
+
+  DefaultASTVisitor::visit (stmt);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-expression-yeast.h 
b/gcc/rust/ast/rust-expression-yeast.h
new file mode 100644
index 000000000000..18712b46aaa0
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_EXPRESSION_YEAST
+#define RUST_EXPRESSION_YEAST
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-desugar-question-mark.h"
+
+namespace Rust {
+namespace AST {
+
+// This visitor takes care of all the expression desugars: try-blocks,
+// error-propagation, etc.
+class ExpressionYeast : public AST::DefaultASTVisitor
+{
+  using AST::DefaultASTVisitor::visit;
+
+public:
+  void go (AST::Crate &);
+
+private:
+  // Dispatch to the proper desugar
+  void dispatch (std::unique_ptr<Expr> &expr);
+
+  void visit (AST::ExprStmt &) override;
+  void visit (AST::CallExpr &) override;
+  void visit (AST::LetStmt &) override;
+  void visit (AST::BlockExpr &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_EXPRESSION_YEAST
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 12cdc2e5dba9..dc59be074167 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -22,6 +22,7 @@
 #include "rust-desugar-question-mark.h"
 #include "rust-desugar-apit.h"
 #include "rust-diagnostics.h"
+#include "rust-expression-yeast.h"
 #include "rust-hir-pattern-analysis.h"
 #include "rust-immutable-name-resolution-context.h"
 #include "rust-unsafe-checker.h"
@@ -985,8 +986,9 @@ Session::expansion (AST::Crate &crate, 
Resolver2_0::NameResolutionContext &ctx)
   // handle AST desugaring
   if (!saw_errors ())
     {
+      AST::ExpressionYeast ().go (crate);
+
       AST::DesugarForLoops ().go (crate);
-      AST::DesugarQuestionMark ().go (crate);
       AST::DesugarApit ().go (crate);
 
       // HACK: we may need a final TopLevel pass

Reply via email to