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