]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: desugar: Add desugar dispatch for all desugars
authorArthur Cohen <arthur.cohen@embecosm.com>
Mon, 21 Jul 2025 09:27:01 +0000 (11:27 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:57 +0000 (16:36 +0200)
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.

gcc/rust/Make-lang.in
gcc/rust/ast/rust-desugar-question-mark.cc
gcc/rust/ast/rust-desugar-question-mark.h
gcc/rust/ast/rust-expression-yeast.cc [new file with mode: 0644]
gcc/rust/ast/rust-expression-yeast.h [new file with mode: 0644]
gcc/rust/rust-session-manager.cc

index c7846892d8955806e0b6489454a2a3b62b2185fd..506435d20038ef51fb958897a94136fc4b54271a 100644 (file)
@@ -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
 
index 4d2933b1bee39f1952566359e50860849d09ea0f..ef2bdb87307fc6044acfadfafb1154d78506a9fb 100644 (file)
@@ -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
index e4c513f461fd6342a3d5791e70f70ce89bf6c7f2..542c52b6310dbb1b55e185a65d287522f9c6ebdb 100644 (file)
@@ -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 (file)
index 0000000..1089b71
--- /dev/null
@@ -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 (file)
index 0000000..18712b4
--- /dev/null
@@ -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
index 12cdc2e5dba9793fbe9212cdd6619e67c869dd0c..dc59be0741678a82cc876699be11a16e6b6545ef 100644 (file)
@@ -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