aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-06 18:24:42 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-07 18:21:53 +0000
commit0ccc245a06e434df2c98d7f9d6036c03e4038842 (patch)
treecf06b88b66d1bd2a54cc1db7e10ea40fc4c09deb /gcc
parentdb7134353447921136a321b8fd78cea78f2c344e (diff)
downloadgcc-0ccc245a06e434df2c98d7f9d6036c03e4038842.zip
gcc-0ccc245a06e434df2c98d7f9d6036c03e4038842.tar.gz
gcc-0ccc245a06e434df2c98d7f9d6036c03e4038842.tar.bz2
With the merge of BlockExprs
Further testing found regressions with implicit returns and type resolution. This unifies the type resolution in block expressions to be more strict and ensure everything bar the final statement should be UnitType.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.h31
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h79
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h42
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h23
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h18
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc16
-rw-r--r--gcc/testsuite/rust.test/compilable/block_expr2.rs14
7 files changed, 81 insertions, 142 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index b823d29..686fb7f 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -460,22 +460,31 @@ public:
return;
}
- fncontext fnctx = ctx->peek_fn ();
- Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
- Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty);
-
- 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);
+ Bvariable *tmp = NULL;
+ bool needs_temp = block_tyty->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, block_tyty);
+
+ 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 code_block = CompileBlock::compile (&expr, ctx, tmp);
auto block_stmt = ctx->get_backend ()->block_statement (code_block);
ctx->add_statement (block_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::StructExprStructFields &struct_expr)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index e6cca19..e7fa3b3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -32,9 +32,9 @@ namespace Resolver {
class TypeCheckExpr : public TypeCheckBase
{
public:
- static TyTy::TyBase *Resolve (HIR::Expr *expr, bool is_final_expr = false)
+ static TyTy::TyBase *Resolve (HIR::Expr *expr)
{
- TypeCheckExpr resolver (is_final_expr);
+ TypeCheckExpr resolver;
expr->accept_vis (resolver);
if (resolver.infered == nullptr)
@@ -277,11 +277,13 @@ public:
void visit (HIR::AssignmentExpr &expr)
{
+ infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+
auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
- infered = lhs->combine (rhs);
- if (infered == nullptr)
+ auto result = lhs->combine (rhs);
+ if (result == nullptr)
{
rust_error_at (expr.get_locus (),
"failure in TypeInference AssignmentExpr");
@@ -320,11 +322,10 @@ public:
return;
}
- // FIXME free the old one
context->insert_type (
Analysis::NodeMapping (expr.get_lhs ()->get_mappings ().get_crate_num (),
ref_node_id, ref, UNKNOWN_LOCAL_DEFID),
- infered->clone ());
+ result->clone ());
}
void visit (HIR::IdentifierExpr &expr)
@@ -592,76 +593,25 @@ public:
void visit (HIR::IfExpr &expr)
{
TypeCheckExpr::Resolve (expr.get_if_condition ());
- auto blk_expr = TypeCheckExpr::Resolve (expr.get_if_block ());
-
- if (is_final_expr
- && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
- {
- auto expected_ty = context->peek_return_type ();
- infered = expected_ty->combine (blk_expr);
- return;
- }
+ TypeCheckExpr::Resolve (expr.get_if_block ());
infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
}
void visit (HIR::IfExprConseqElse &expr)
{
- // check and resolve all types in the conditional var
TypeCheckExpr::Resolve (expr.get_if_condition ());
-
auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ());
auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ());
- TyTy::TyBase *if_block_tyty = nullptr;
- if (expr.get_if_block ()->has_expr ())
- if_block_tyty
- = TypeCheckExpr::Resolve (expr.get_if_block ()->expr.get ());
- else
- if_block_tyty = if_blk_resolved;
-
- TyTy::TyBase *else_block_tyty = nullptr;
- if (expr.get_else_block ()->has_expr ())
- else_block_tyty
- = TypeCheckExpr::Resolve (expr.get_else_block ()->expr.get ());
- else
- else_block_tyty = else_blk_resolved;
-
- if (context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
- {
- // this must combine to what the type is expected
- // this might be a parameter or the last expr in an if + else in a
- // BlockExpr then it must resolve to fn return type else its a unit-type
- auto expected_ty
- = is_final_expr
- ? context->peek_return_type ()
- : new TyTy::UnitType (expr.get_mappings ().get_hirid ());
-
- auto if_blk_combined = expected_ty->combine (if_block_tyty);
- auto else_blk_combined = expected_ty->combine (else_block_tyty);
-
- infered = if_blk_combined->combine (else_blk_combined);
- return;
- }
-
- infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ infered = if_blk_resolved->combine (else_blk_resolved);
}
void visit (HIR::IfExprConseqIf &expr)
{
TypeCheckExpr::Resolve (expr.get_if_condition ());
- auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ());
- auto elif_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
-
- if (is_final_expr
- && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
- {
- auto expected_ty = context->peek_return_type ();
-
- infered = expected_ty->combine (if_blk);
- infered = infered->combine (elif_blk);
- return;
- }
+ TypeCheckExpr::Resolve (expr.get_if_block ());
+ TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
}
@@ -817,9 +767,8 @@ public:
}
private:
- TypeCheckExpr (bool is_final_expr)
- : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr),
- is_final_expr (is_final_expr)
+ TypeCheckExpr ()
+ : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr)
{}
bool
@@ -870,8 +819,6 @@ private:
TyTy::TyBase *infered;
TyTy::TyBase *infered_array_elems;
-
- bool is_final_expr;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index c8d161a..a0a4fda 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -170,23 +170,12 @@ public:
auto expected_ret_tyty = resolve_fn_type->return_type ();
context->push_return_type (expected_ret_tyty);
- TypeCheckExpr::Resolve (function.function_body.get ());
- if (function.function_body->has_expr ())
- {
- auto resolved
- = TypeCheckExpr::Resolve (function.function_body->expr.get ());
+ auto result = TypeCheckExpr::Resolve (function.function_body.get ());
+ auto ret_resolved = expected_ret_tyty->combine (result);
+ if (ret_resolved == nullptr)
+ return;
- auto ret_resolved = expected_ret_tyty->combine (resolved);
- if (ret_resolved == nullptr)
- {
- rust_error_at (function.function_body->expr->get_locus_slow (),
- "failed to resolve final expression");
- return;
- }
-
- context->peek_return_type ()->append_reference (
- ret_resolved->get_ref ());
- }
+ context->peek_return_type ()->append_reference (ret_resolved->get_ref ());
context->pop_return_type ();
}
@@ -213,23 +202,12 @@ public:
auto expected_ret_tyty = resolve_fn_type->return_type ();
context->push_return_type (expected_ret_tyty);
- TypeCheckExpr::Resolve (method.get_function_body ().get ());
- if (method.get_function_body ()->has_expr ())
- {
- auto resolved
- = TypeCheckExpr::Resolve (method.get_function_body ()->expr.get ());
+ auto result = TypeCheckExpr::Resolve (method.get_function_body ().get ());
+ auto ret_resolved = expected_ret_tyty->combine (result);
+ if (ret_resolved == nullptr)
+ return;
- auto ret_resolved = expected_ret_tyty->combine (resolved);
- if (ret_resolved == nullptr)
- {
- rust_error_at (method.get_function_body ()->expr->get_locus_slow (),
- "failed to resolve final expression");
- return;
- }
-
- context->peek_return_type ()->append_reference (
- ret_resolved->get_ref ());
- }
+ context->peek_return_type ()->append_reference (ret_resolved->get_ref ());
context->pop_return_type ();
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 06be1ac..fbe2056 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -75,23 +75,12 @@ public:
auto expected_ret_tyty = resolve_fn_type->return_type ();
context->push_return_type (expected_ret_tyty);
- TypeCheckExpr::Resolve (function.function_body.get ());
- if (function.function_body->has_expr ())
- {
- auto resolved
- = TypeCheckExpr::Resolve (function.function_body->expr.get ());
-
- auto ret_resolved = expected_ret_tyty->combine (resolved);
- if (ret_resolved == nullptr)
- {
- rust_error_at (function.function_body->expr->get_locus_slow (),
- "failed to resolve final expression");
- return;
- }
-
- context->peek_return_type ()->append_reference (
- ret_resolved->get_ref ());
- }
+ auto result = TypeCheckExpr::Resolve (function.function_body.get ());
+ auto ret_resolved = expected_ret_tyty->combine (result);
+ if (ret_resolved == nullptr)
+ return;
+
+ context->peek_return_type ()->append_reference (ret_resolved->get_ref ());
context->pop_return_type ();
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index e04284e..83fdf11 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -30,21 +30,21 @@ namespace Resolver {
class TypeCheckStmt : public TypeCheckBase
{
public:
- static TyTy::TyBase *Resolve (HIR::Stmt *stmt, bool is_final_stmt)
+ static TyTy::TyBase *Resolve (HIR::Stmt *stmt)
{
- TypeCheckStmt resolver (is_final_stmt);
+ TypeCheckStmt resolver;
stmt->accept_vis (resolver);
return resolver.infered;
}
void visit (HIR::ExprStmtWithBlock &stmt)
{
- infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt);
+ infered = TypeCheckExpr::Resolve (stmt.get_expr ());
}
void visit (HIR::ExprStmtWithoutBlock &stmt)
{
- infered = TypeCheckExpr::Resolve (stmt.get_expr (), is_final_stmt);
+ infered = TypeCheckExpr::Resolve (stmt.get_expr ());
}
void visit (HIR::LetStmt &stmt)
@@ -54,8 +54,7 @@ public:
TyTy::TyBase *init_expr_ty = nullptr;
if (stmt.has_init_expr ())
{
- init_expr_ty
- = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt);
+ init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ());
if (init_expr_ty == nullptr)
return;
@@ -106,13 +105,10 @@ public:
}
private:
- TypeCheckStmt (bool is_final_stmt)
- : TypeCheckBase (), infered (nullptr), is_final_stmt (is_final_stmt)
- {}
+ TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {}
TyTy::TyBase *infered;
- bool is_final_stmt;
-}; // namespace Resolver
+};
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 681d023..3044a6f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -109,10 +109,11 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
bool is_final_stmt = expr.is_final_stmt (s);
- bool is_final_expr = is_final_stmt && !expr.has_expr ();
+ bool is_final_expr
+ = is_final_stmt && (!expr.has_expr () || !expr.tail_expr_reachable ());
- auto infered = TypeCheckStmt::Resolve (s, is_final_expr);
- if (infered == nullptr)
+ auto resolved = TypeCheckStmt::Resolve (s);
+ if (resolved == nullptr)
{
rust_error_at (s->get_locus_slow (), "failure to resolve type");
return false;
@@ -121,7 +122,12 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
if (is_final_expr)
{
delete block_tyty;
- block_tyty = infered;
+ block_tyty = resolved;
+ }
+ else if (resolved->get_kind () != TyTy::TypeKind::UNIT)
+ {
+ rust_error_at (s->get_locus_slow (), "expected () got %s",
+ infered->as_string ().c_str ());
}
return true;
@@ -131,7 +137,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
{
delete block_tyty;
- block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get (), true);
+ block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get ());
}
infered = block_tyty->clone ();
diff --git a/gcc/testsuite/rust.test/compilable/block_expr2.rs b/gcc/testsuite/rust.test/compilable/block_expr2.rs
new file mode 100644
index 0000000..a66ca7b
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/block_expr2.rs
@@ -0,0 +1,14 @@
+fn test() -> i32 {
+ 123
+}
+
+fn main() {
+ let a = { test() };
+ let b = {
+ if a > 10 {
+ a - 1
+ } else {
+ a + 1
+ }
+ };
+}