Branch data Line data Source code
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-desugar-question-mark.h"
20 : : #include "rust-ast-builder.h"
21 : :
22 : : namespace Rust {
23 : : namespace AST {
24 : :
25 : 1 : DesugarQuestionMark::DesugarQuestionMark () {}
26 : :
27 : : void
28 : 1 : DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
29 : : {
30 : 1 : rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation);
31 : :
32 : 1 : auto original = static_cast<ErrorPropagationExpr &> (*ptr);
33 : 1 : auto desugared = DesugarQuestionMark ().desugar (original);
34 : :
35 : 1 : ptr = std::move (desugared);
36 : 1 : }
37 : :
38 : : MatchArm
39 : 2 : make_match_arm (std::unique_ptr<Pattern> &&pattern)
40 : : {
41 : 2 : auto loc = pattern->get_locus ();
42 : :
43 : 2 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
44 : 2 : patterns.emplace_back (std::move (pattern));
45 : :
46 : 2 : return MatchArm (std::move (patterns), loc);
47 : 2 : }
48 : :
49 : : MatchCase
50 : 1 : ok_case (Builder &builder)
51 : : {
52 : 1 : auto val = builder.identifier_pattern ("val");
53 : :
54 : 1 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
55 : 1 : patterns.emplace_back (std::move (val));
56 : :
57 : 1 : auto pattern_item = std::unique_ptr<TupleStructItems> (
58 : 1 : new TupleStructItemsNoRange (std::move (patterns)));
59 : 1 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
60 : 2 : builder.path_in_expression (LangItem::Kind::RESULT_OK),
61 : 1 : std::move (pattern_item)));
62 : :
63 : 1 : auto arm = make_match_arm (std::move (pattern));
64 : :
65 : 1 : auto ret_val = builder.identifier ("val");
66 : :
67 : 1 : return MatchCase (std::move (arm), std::move (ret_val));
68 : 1 : }
69 : :
70 : : MatchCase
71 : 1 : err_case (Builder &builder)
72 : : {
73 : : // TODO: We need to handle the case where there is an enclosing `try {}`
74 : : // block, as that will create an additional block label that we can break to.
75 : : // This allows try blocks to use the question mark operator without having the
76 : : // offending statement early return from the enclosing function
77 : : // FIXME: How to mark that there is an enclosing block label?
78 : :
79 : 1 : auto val = builder.identifier_pattern ("err");
80 : :
81 : 1 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
82 : 1 : patterns.emplace_back (std::move (val));
83 : :
84 : 1 : auto pattern_item = std::unique_ptr<TupleStructItems> (
85 : 1 : new TupleStructItemsNoRange (std::move (patterns)));
86 : 1 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
87 : 2 : builder.path_in_expression (LangItem::Kind::RESULT_ERR),
88 : 1 : std::move (pattern_item)));
89 : :
90 : 1 : auto arm = make_match_arm (std::move (pattern));
91 : :
92 : 1 : auto try_from_err = std::make_unique<PathInExpression> (
93 : 1 : builder.path_in_expression (LangItem::Kind::TRY_FROM_ERROR));
94 : 1 : auto from_from = std::make_unique<PathInExpression> (
95 : 1 : builder.path_in_expression (LangItem::Kind::FROM_FROM));
96 : :
97 : 1 : auto early_return = builder.return_expr (
98 : 2 : builder.call (std::move (try_from_err),
99 : 2 : builder.call (std::move (from_from),
100 : 3 : builder.identifier ("err"))));
101 : :
102 : 1 : return MatchCase (std::move (arm), std::move (early_return));
103 : 1 : }
104 : :
105 : : std::unique_ptr<Expr>
106 : 1 : DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
107 : : {
108 : 1 : auto builder = Builder (expr.get_locus ());
109 : :
110 : : // Try::into_result(<expr>)
111 : 1 : auto try_into = std::make_unique<PathInExpression> (
112 : 1 : builder.path_in_expression (LangItem::Kind::TRY_INTO_RESULT));
113 : 1 : auto call = builder.call (std::move (try_into),
114 : 3 : expr.get_propagating_expr ().clone_expr ());
115 : :
116 : : // Ok(val) => val,
117 : 1 : auto ok_match_case = ok_case (builder);
118 : : // Err(err) => return Try::from_error(From::from(err)),
119 : 1 : auto err_match_case = err_case (builder);
120 : :
121 : 1 : auto cases = std::vector<MatchCase> ();
122 : 1 : cases.emplace_back (ok_match_case);
123 : 1 : cases.emplace_back (err_match_case);
124 : :
125 : : // match <call> {
126 : : // <ok_arm>
127 : : // <err_arm>
128 : : // }
129 : 1 : return std::unique_ptr<MatchExpr> (new MatchExpr (std::move (call),
130 : : std::move (cases), {}, {},
131 : 1 : expr.get_locus ()));
132 : 3 : }
133 : :
134 : : } // namespace AST
135 : : } // namespace Rust
|