Skip to content

Commit 42db673

Browse files
authored
Try #380:
2 parents bb85500 + 3aeb9f4 commit 42db673

40 files changed

+418
-96
lines changed

gcc/rust/ast/rust-expr.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -2828,7 +2828,7 @@ class BlockExpr : public ExprWithBlock
28282828
std::vector<Attribute> outer_attrs;
28292829
std::vector<Attribute> inner_attrs;
28302830
std::vector<std::unique_ptr<Stmt> > statements;
2831-
std::unique_ptr<ExprWithoutBlock> expr;
2831+
std::unique_ptr<Expr> expr;
28322832
Location locus;
28332833
bool marked_for_strip = false;
28342834

@@ -2842,7 +2842,7 @@ class BlockExpr : public ExprWithBlock
28422842
bool has_tail_expr () const { return expr != nullptr; }
28432843

28442844
BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
2845-
std::unique_ptr<ExprWithoutBlock> block_expr,
2845+
std::unique_ptr<Expr> block_expr,
28462846
std::vector<Attribute> inner_attribs,
28472847
std::vector<Attribute> outer_attribs, Location locus)
28482848
: outer_attrs (std::move (outer_attribs)),
@@ -2859,7 +2859,7 @@ class BlockExpr : public ExprWithBlock
28592859
{
28602860
// guard to protect from null pointer dereference
28612861
if (other.expr != nullptr)
2862-
expr = other.expr->clone_expr_without_block ();
2862+
expr = other.expr->clone_expr ();
28632863

28642864
statements.reserve (other.statements.size ());
28652865
for (const auto &e : other.statements)
@@ -2877,7 +2877,7 @@ class BlockExpr : public ExprWithBlock
28772877

28782878
// guard to protect from null pointer dereference
28792879
if (other.expr != nullptr)
2880-
expr = other.expr->clone_expr_without_block ();
2880+
expr = other.expr->clone_expr ();
28812881
else
28822882
expr = nullptr;
28832883

@@ -2929,7 +2929,7 @@ class BlockExpr : public ExprWithBlock
29292929
std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
29302930

29312931
// TODO: is this better? Or is a "vis_block" better?
2932-
std::unique_ptr<ExprWithoutBlock> &get_tail_expr ()
2932+
std::unique_ptr<Expr> &get_tail_expr ()
29332933
{
29342934
rust_assert (has_tail_expr ());
29352935
return expr;

gcc/rust/ast/rust-stmt.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,17 @@ class ExprStmtWithoutBlock : public ExprStmt
269269
class ExprStmtWithBlock : public ExprStmt
270270
{
271271
std::unique_ptr<ExprWithBlock> expr;
272+
bool semicolon_followed;
272273

273274
public:
274275
std::string as_string () const override;
275276

276277
std::vector<LetStmt *> locals;
277278

278-
ExprStmtWithBlock (std::unique_ptr<ExprWithBlock> expr, Location locus)
279-
: ExprStmt (locus), expr (std::move (expr))
279+
ExprStmtWithBlock (std::unique_ptr<ExprWithBlock> expr, Location locus,
280+
bool semicolon_followed)
281+
: ExprStmt (locus), expr (std::move (expr)),
282+
semicolon_followed (semicolon_followed)
280283
{}
281284

282285
// Copy constructor with clone
@@ -318,6 +321,8 @@ class ExprStmtWithBlock : public ExprStmt
318321
return expr;
319322
}
320323

324+
bool is_semicolon_followed () const { return semicolon_followed; }
325+
321326
protected:
322327
/* Use covariance to implement clone function as returning this object rather
323328
* than base */

gcc/rust/backend/rust-compile-context.h

+5
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,11 @@ class TyTyResolveCompile : public TyTy::TyVisitor
501501
translated = compiled_type;
502502
}
503503

504+
void visit (TyTy::NeverType &) override
505+
{
506+
translated = ctx->get_backend ()->void_type ();
507+
}
508+
504509
private:
505510
TyTyResolveCompile (Context *ctx) : ctx (ctx), translated (nullptr) {}
506511

gcc/rust/backend/rust-compile-tyty.h

+5
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ class TyTyCompile : public TyTy::TyVisitor
222222
= backend->named_type ("str", raw_str, Linemap::predeclared_location ());
223223
}
224224

225+
void visit (TyTy::NeverType &) override
226+
{
227+
translated = backend->void_type ();
228+
}
229+
225230
private:
226231
TyTyCompile (::Backend *backend)
227232
: backend (backend), translated (nullptr),

gcc/rust/backend/rust-compile.cc

+4-5
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ CompileBlock::visit (HIR::BlockExpr &expr)
256256
}
257257
}
258258

259-
if (expr.has_expr () && expr.tail_expr_reachable ())
259+
if (expr.has_expr ())
260260
{
261261
// the previous passes will ensure this is a valid return
262262
// dead code elimination should remove any bad trailing expressions
@@ -410,15 +410,14 @@ HIRCompileBase::compile_function_body (
410410
}
411411
}
412412

413-
if (function_body->has_expr () && function_body->tail_expr_reachable ())
413+
if (function_body->has_expr ())
414414
{
415415
// the previous passes will ensure this is a valid return
416416
// dead code elimination should remove any bad trailing expressions
417417
Bexpression *compiled_expr
418418
= CompileExpr::Compile (function_body->expr.get (), ctx);
419-
rust_assert (compiled_expr != nullptr);
420419

421-
if (has_return_type)
420+
if (has_return_type && compiled_expr)
422421
{
423422
std::vector<Bexpression *> retstmts;
424423
retstmts.push_back (compiled_expr);
@@ -428,7 +427,7 @@ HIRCompileBase::compile_function_body (
428427
function_body->get_final_expr ()->get_locus_slow ());
429428
ctx->add_statement (ret);
430429
}
431-
else
430+
else if (compiled_expr)
432431
{
433432
Bstatement *final_stmt
434433
= ctx->get_backend ()->expression_statement (fndecl, compiled_expr);

gcc/rust/hir/rust-ast-lower-stmt.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class ASTLoweringStmt : public ASTLoweringBase
5959
translated
6060
= new HIR::ExprStmtWithBlock (mapping,
6161
std::unique_ptr<HIR::ExprWithBlock> (expr),
62-
stmt.get_locus ());
62+
stmt.get_locus (),
63+
!stmt.is_semicolon_followed ());
6364
mappings->insert_location (crate_num, mapping.get_hirid (),
6465
stmt.get_locus ());
6566
mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated);

gcc/rust/hir/rust-ast-lower.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr)
9090
return true;
9191
});
9292

93-
bool tail_reachable = expr.has_tail_expr () && !block_did_terminate;
93+
bool tail_reachable = !block_did_terminate;
9494
if (expr.has_tail_expr () && block_did_terminate)
9595
{
9696
// warning unreachable tail expressions

gcc/rust/hir/tree/rust-hir-expr.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -2489,7 +2489,7 @@ class BlockExpr : public ExprWithBlock
24892489
std::vector<Attribute> inner_attrs;
24902490

24912491
std::vector<std::unique_ptr<Stmt> > statements;
2492-
std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements
2492+
std::unique_ptr<Expr> expr; // inlined from Statements
24932493

24942494
bool tail_reachable;
24952495
Location locus;
@@ -2502,11 +2502,11 @@ class BlockExpr : public ExprWithBlock
25022502
// Returns whether the block contains an expression
25032503
bool has_expr () const { return expr != nullptr; }
25042504

2505-
bool tail_expr_reachable () const { return tail_reachable; }
2505+
bool is_tail_reachable () const { return tail_reachable; }
25062506

25072507
BlockExpr (Analysis::NodeMapping mappings,
25082508
std::vector<std::unique_ptr<Stmt> > block_statements,
2509-
std::unique_ptr<ExprWithoutBlock> block_expr, bool tail_reachable,
2509+
std::unique_ptr<Expr> block_expr, bool tail_reachable,
25102510
std::vector<Attribute> inner_attribs,
25112511
std::vector<Attribute> outer_attribs, Location locus)
25122512
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
@@ -2522,7 +2522,7 @@ class BlockExpr : public ExprWithBlock
25222522
{
25232523
// guard to protect from null pointer dereference
25242524
if (other.expr != nullptr)
2525-
expr = other.expr->clone_expr_without_block ();
2525+
expr = other.expr->clone_expr ();
25262526

25272527
statements.reserve (other.statements.size ());
25282528
for (const auto &e : other.statements)
@@ -2534,7 +2534,7 @@ class BlockExpr : public ExprWithBlock
25342534
{
25352535
ExprWithBlock::operator= (other);
25362536
// statements = other.statements;
2537-
expr = other.expr->clone_expr_without_block ();
2537+
expr = other.expr->clone_expr ();
25382538
inner_attrs = other.inner_attrs;
25392539
locus = other.locus;
25402540
// outer_attrs = other.outer_attrs;
@@ -2580,7 +2580,7 @@ class BlockExpr : public ExprWithBlock
25802580
return statements[statements.size () - 1]->get_locus_slow ();
25812581
}
25822582

2583-
std::unique_ptr<ExprWithoutBlock> &get_final_expr () { return expr; }
2583+
std::unique_ptr<Expr> &get_final_expr () { return expr; }
25842584

25852585
std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
25862586

gcc/rust/hir/tree/rust-hir-stmt.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,16 @@ class ExprStmtWithoutBlock : public ExprStmt
193193
class ExprStmtWithBlock : public ExprStmt
194194
{
195195
std::unique_ptr<ExprWithBlock> expr;
196+
bool must_be_unit;
196197

197198
public:
198199
std::string as_string () const override;
199200

200201
ExprStmtWithBlock (Analysis::NodeMapping mappings,
201-
std::unique_ptr<ExprWithBlock> expr, Location locus)
202-
: ExprStmt (std::move (mappings), locus), expr (std::move (expr))
202+
std::unique_ptr<ExprWithBlock> expr, Location locus,
203+
bool must_be_unit)
204+
: ExprStmt (std::move (mappings), locus), expr (std::move (expr)),
205+
must_be_unit (must_be_unit)
203206
{}
204207

205208
// Copy constructor with clone
@@ -224,6 +227,8 @@ class ExprStmtWithBlock : public ExprStmt
224227

225228
ExprWithBlock *get_expr () { return expr.get (); }
226229

230+
bool is_unit_check_needed () const override { return must_be_unit; }
231+
227232
protected:
228233
/* Use covariance to implement clone function as returning this object rather
229234
* than base */

gcc/rust/hir/tree/rust-hir.h

+2
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ class Stmt
723723
* methods. */
724724
virtual Location get_locus_slow () const { return Location (); }
725725

726+
virtual bool is_unit_check_needed () const { return false; }
727+
726728
const Analysis::NodeMapping &get_mappings () const { return mappings; }
727729

728730
protected:

gcc/rust/parse/rust-parse-impl.h

+44-17
Original file line numberDiff line numberDiff line change
@@ -7022,11 +7022,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (
70227022
}
70237023
}
70247024

7025-
/* Parses a expression statement containing an expression with block.
7026-
* Disambiguates internally. */
70277025
template <typename ManagedTokenSource>
7028-
std::unique_ptr<AST::ExprStmtWithBlock>
7029-
Parser<ManagedTokenSource>::parse_expr_stmt_with_block (
7026+
std::unique_ptr<AST::ExprWithBlock>
7027+
Parser<ManagedTokenSource>::parse_expr_with_block (
70307028
std::vector<AST::Attribute> outer_attrs)
70317029
{
70327030
std::unique_ptr<AST::ExprWithBlock> expr_parsed = nullptr;
@@ -7113,9 +7111,23 @@ Parser<ManagedTokenSource>::parse_expr_stmt_with_block (
71137111
return nullptr;
71147112
}
71157113

7114+
return expr_parsed;
7115+
}
7116+
7117+
/* Parses a expression statement containing an expression with block.
7118+
* Disambiguates internally. */
7119+
template <typename ManagedTokenSource>
7120+
std::unique_ptr<AST::ExprStmtWithBlock>
7121+
Parser<ManagedTokenSource>::parse_expr_stmt_with_block (
7122+
std::vector<AST::Attribute> outer_attrs)
7123+
{
7124+
auto expr_parsed = parse_expr_with_block (std::move (outer_attrs));
7125+
auto locus = expr_parsed->get_locus ();
7126+
71167127
// return expr stmt created from expr
71177128
return std::unique_ptr<AST::ExprStmtWithBlock> (
7118-
new AST::ExprStmtWithBlock (std::move (expr_parsed), t->get_locus ()));
7129+
new AST::ExprStmtWithBlock (std::move (expr_parsed), locus,
7130+
lexer.peek_token ()->get_id () == SEMICOLON));
71197131
}
71207132

71217133
/* Parses an expression statement containing an expression without block.
@@ -7286,7 +7298,7 @@ Parser<ManagedTokenSource>::parse_block_expr (
72867298

72877299
// parse statements and expression
72887300
std::vector<std::unique_ptr<AST::Stmt>> stmts;
7289-
std::unique_ptr<AST::ExprWithoutBlock> expr = nullptr;
7301+
std::unique_ptr<AST::Expr> expr = nullptr;
72907302

72917303
const_TokenPtr t = lexer.peek_token ();
72927304
while (t->get_id () != RIGHT_CURLY)
@@ -11438,6 +11450,29 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
1143811450
}
1143911451
}
1144011452

11453+
template <typename ManagedTokenSource>
11454+
ExprOrStmt
11455+
Parser<ManagedTokenSource>::parse_stmt_or_expr_with_block (
11456+
std::vector<AST::Attribute> outer_attrs)
11457+
{
11458+
auto expr = parse_expr_with_block (std::move (outer_attrs));
11459+
auto tok = lexer.peek_token ();
11460+
11461+
// tail expr in a block expr
11462+
if (tok->get_id () == RIGHT_CURLY)
11463+
return ExprOrStmt (std::move (expr));
11464+
11465+
// internal block expr must either have semicolons followed, or evaluate to ()
11466+
auto locus = expr->get_locus_slow ();
11467+
std::unique_ptr<AST::ExprStmtWithBlock> stmt (
11468+
new AST::ExprStmtWithBlock (std::move (expr), locus,
11469+
tok->get_id () == SEMICOLON));
11470+
if (tok->get_id () == SEMICOLON)
11471+
lexer.skip_token ();
11472+
11473+
return ExprOrStmt (std::move (stmt));
11474+
}
11475+
1144111476
/* Parses a statement or expression (depending on whether a trailing semicolon
1144211477
* exists). Useful for block expressions where it cannot be determined through
1144311478
* lookahead whether it is a statement or expression to be parsed. */
@@ -11508,9 +11543,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
1150811543
{
1150911544
case LEFT_CURLY: {
1151011545
// unsafe block
11511-
std::unique_ptr<AST::ExprStmtWithBlock> stmt (
11512-
parse_expr_stmt_with_block (std::move (outer_attrs)));
11513-
return ExprOrStmt (std::move (stmt));
11546+
return parse_stmt_or_expr_with_block (std::move (outer_attrs));
1151411547
}
1151511548
case TRAIT: {
1151611549
// unsafe trait
@@ -11577,11 +11610,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
1157711610
case MATCH_TOK:
1157811611
case LEFT_CURLY:
1157911612
case ASYNC: {
11580-
// all expressions with block, so cannot be final expr without block in
11581-
// function
11582-
std::unique_ptr<AST::ExprStmtWithBlock> stmt (
11583-
parse_expr_stmt_with_block (std::move (outer_attrs)));
11584-
return ExprOrStmt (std::move (stmt));
11613+
return parse_stmt_or_expr_with_block (std::move (outer_attrs));
1158511614
}
1158611615
case LIFETIME: {
1158711616
/* FIXME: are there any expressions without blocks that can have
@@ -11592,9 +11621,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
1159211621
&& (t2->get_id () == LOOP || t2->get_id () == WHILE
1159311622
|| t2->get_id () == FOR))
1159411623
{
11595-
std::unique_ptr<AST::ExprStmtWithBlock> stmt (
11596-
parse_expr_stmt_with_block (std::move (outer_attrs)));
11597-
return ExprOrStmt (std::move (stmt));
11624+
return parse_stmt_or_expr_with_block (std::move (outer_attrs));
1159811625
}
1159911626
else
1160011627
{

0 commit comments

Comments
 (0)