diff options
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 63 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/block_expr3.rs | 13 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs | 13 |
4 files changed, 80 insertions, 15 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 686fb7f..2dabe01 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -417,7 +417,6 @@ public: void visit (HIR::IfExprConseqElse &expr) { - // this can be a return expression TyTy::TyBase *if_type = nullptr; if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &if_type)) @@ -427,27 +426,67 @@ public: return; } - fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + Bvariable *tmp = NULL; + bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); - bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; - Bvariable *tmp = ctx->get_backend ()->temporary_variable ( - fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, - expr.get_locus (), &ret_var_stmt); - ctx->add_statement (ret_var_stmt); + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + } auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); - translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + if (tmp != NULL) + { + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::IfExprConseqIf &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); + TyTy::TyBase *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT; + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated + = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } } void visit (HIR::BlockExpr &expr) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index e7fa3b3..43e51c8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -610,10 +610,10 @@ public: void visit (HIR::IfExprConseqIf &expr) { TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); - TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto else_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); - infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + infered = if_blk->combine (else_blk); } void visit (HIR::BlockExpr &expr); diff --git a/gcc/testsuite/rust.test/compilable/block_expr3.rs b/gcc/testsuite/rust.test/compilable/block_expr3.rs new file mode 100644 index 0000000..a8b2f27 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/block_expr3.rs @@ -0,0 +1,13 @@ +fn main() { + let x = 111; + + let a = { + if x == 10 { + 123 + } else if x < 10 { + 456 + } else { + 789 + } + }; +} diff --git a/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs b/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs new file mode 100644 index 0000000..eda6d17 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs @@ -0,0 +1,13 @@ +fn test(x: i32) -> i32 { + if x == 10 { + 123 + } else if x < 10 { + 456 + } else { + 789 + } +} + +fn main() { + let a = test(1); +} |