Skip to content

Commit 39a5c15

Browse files
committed
desugar: Handle try-blocks
gcc/rust/ChangeLog: * Make-lang.in: Compile it. * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Dispatch to try-block desugar. * ast/rust-desugar-try-block.cc: New file. * ast/rust-desugar-try-block.h: New file. gcc/testsuite/ChangeLog: * rust/compile/try_block1.rs: New test.
1 parent e7f5681 commit 39a5c15

File tree

5 files changed

+196
-1
lines changed

5 files changed

+196
-1
lines changed

gcc/rust/Make-lang.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ GRS_OBJS = \
246246
rust/rust-desugar-for-loops.o \
247247
rust/rust-desugar-question-mark.o \
248248
rust/rust-desugar-apit.o \
249-
# rust/rust-desugar-try-block.o \
249+
rust/rust-desugar-try-block.o \
250250
$(END)
251251
# removed object files from here
252252

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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-try-block.h"
20+
#include "rust-ast-builder.h"
21+
#include "rust-expr.h"
22+
23+
namespace Rust {
24+
namespace AST {
25+
26+
DesugarTryBlock::DesugarTryBlock () {}
27+
28+
void
29+
DesugarTryBlock::go (std::unique_ptr<Expr> &ptr)
30+
{
31+
auto original = static_cast<TryExpr &> (*ptr);
32+
auto desugared = DesugarTryBlock ().desugar (original);
33+
34+
ptr = std::move (desugared);
35+
}
36+
37+
std::unique_ptr<Expr>
38+
DesugarTryBlock::desugar (TryExpr &expr)
39+
{
40+
auto builder = Builder (expr.get_locus ());
41+
auto &block = expr.get_block_expr ();
42+
43+
if (block.has_statements ())
44+
rust_sorry_at (expr.get_locus (),
45+
"cannot desugar try-blocks with statements");
46+
47+
auto tail_expr = builder.tuple ();
48+
49+
if (block.has_tail_expr ())
50+
tail_expr = block.get_tail_expr ().clone_expr ();
51+
52+
// Wrap in Try::from_ok call
53+
auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK);
54+
auto call = builder.call (ptrify (from_ok), std::move (tail_expr));
55+
56+
return builder.block (std::move (call));
57+
}
58+
59+
} // namespace AST
60+
} // namespace Rust
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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_DESUGAR_TRY_BLOCK
20+
#define RUST_DESUGAR_TRY_BLOCK
21+
22+
#include "rust-expr.h"
23+
24+
namespace Rust {
25+
namespace AST {
26+
27+
// FIXME: Add documentation
28+
class DesugarTryBlock
29+
{
30+
public:
31+
static void go (std::unique_ptr<Expr> &ptr);
32+
33+
private:
34+
DesugarTryBlock ();
35+
36+
std::unique_ptr<Expr> desugar (TryExpr &);
37+
};
38+
39+
} // namespace AST
40+
} // namespace Rust
41+
42+
#endif // ! RUST_DESUGAR_TRY_BLOCK

gcc/rust/ast/rust-expression-yeast.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "rust-expression-yeast.h"
2020
#include "rust-ast-visitor.h"
2121
#include "rust-desugar-question-mark.h"
22+
#include "rust-desugar-try-block.h"
2223
#include "rust-ast-full.h"
2324

2425
namespace Rust {
@@ -39,6 +40,9 @@ ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
3940
case Expr::Kind::ErrorPropagation:
4041
DesugarQuestionMark::go (expr);
4142
break;
43+
case Expr::Kind::Try:
44+
DesugarTryBlock::go (expr);
45+
break;
4246

4347
default:
4448
break;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// { dg-additional-options "-frust-edition=2018" }
2+
3+
#[lang = "sized"]
4+
trait Sized {}
5+
6+
enum Result<T, E> {
7+
Ok(T),
8+
Err(E)
9+
}
10+
11+
pub trait Try {
12+
/// The type of this value when viewed as successful.
13+
#[unstable(feature = "try_trait", issue = "42327")]
14+
type Ok;
15+
/// The type of this value when viewed as failed.
16+
#[unstable(feature = "try_trait", issue = "42327")]
17+
type Error;
18+
19+
/// Applies the "?" operator. A return of `Ok(t)` means that the
20+
/// execution should continue normally, and the result of `?` is the
21+
/// value `t`. A return of `Err(e)` means that execution should branch
22+
/// to the innermost enclosing `catch`, or return from the function.
23+
///
24+
/// If an `Err(e)` result is returned, the value `e` will be "wrapped"
25+
/// in the return type of the enclosing scope (which must itself implement
26+
/// `Try`). Specifically, the value `X::from_error(From::from(e))`
27+
/// is returned, where `X` is the return type of the enclosing function.
28+
#[lang = "into_result"]
29+
#[unstable(feature = "try_trait", issue = "42327")]
30+
fn into_result(self) -> Result<Self::Ok, Self::Error>;
31+
32+
/// Wrap an error value to construct the composite result. For example,
33+
/// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
34+
#[lang = "from_error"]
35+
#[unstable(feature = "try_trait", issue = "42327")]
36+
fn from_error(v: Self::Error) -> Self;
37+
38+
/// Wrap an OK value to construct the composite result. For example,
39+
/// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
40+
#[lang = "from_ok"]
41+
#[unstable(feature = "try_trait", issue = "42327")]
42+
fn from_ok(v: Self::Ok) -> Self;
43+
}
44+
45+
pub struct NoneError;
46+
47+
48+
pub enum Option<T> {
49+
/// No value
50+
None,
51+
/// Some value `T`
52+
Some(T),
53+
}
54+
55+
impl<T> Option<T> {
56+
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
57+
match self {
58+
Some(ok) => Result::Ok(ok),
59+
None => Result::Err(err)
60+
}
61+
}
62+
}
63+
64+
use Option::*;
65+
66+
#[unstable(feature = "try_trait", issue = "42327")]
67+
impl<T> Try for Option<T> {
68+
type Ok = T;
69+
type Error = NoneError;
70+
71+
#[inline]
72+
fn into_result(self) -> Result<T, NoneError> {
73+
self.ok_or(NoneError)
74+
}
75+
76+
#[inline]
77+
fn from_ok(v: T) -> Self {
78+
Some(v)
79+
}
80+
81+
#[inline]
82+
fn from_error(_: NoneError) -> Self {
83+
None
84+
}
85+
}
86+
87+
fn main() {
88+
let _: Option<i32> = try { 15i32 };
89+
}

0 commit comments

Comments
 (0)