gccrs: Add missing coercion site logic to return expressions
gcc/rust/ChangeLog: * backend/rust-compile-base.cc: track return type in fncontext * backend/rust-compile-context.h (struct fncontext): likewise * backend/rust-compile-expr.cc (CompileExpr::visit): apply coercion site (CompileExpr::generate_closure_function): update push_context * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise gcc/testsuite/ChangeLog: * rust/execute/torture/coercion3.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
This commit is contained in:
parent
f91d7d3906
commit
b90dc2bdd2
5 changed files with 63 additions and 9 deletions
|
@ -639,7 +639,7 @@ HIRCompileBase::compile_function (
|
||||||
|
|
||||||
ctx->add_statement (ret_var_stmt);
|
ctx->add_statement (ret_var_stmt);
|
||||||
|
|
||||||
ctx->push_fn (fndecl, return_address);
|
ctx->push_fn (fndecl, return_address, tyret);
|
||||||
compile_function_body (fndecl, *function_body, tyret);
|
compile_function_body (fndecl, *function_body, tyret);
|
||||||
tree bind_tree = ctx->pop_block ();
|
tree bind_tree = ctx->pop_block ();
|
||||||
|
|
||||||
|
@ -712,7 +712,7 @@ HIRCompileBase::compile_constant_item (
|
||||||
&ret_var_stmt);
|
&ret_var_stmt);
|
||||||
|
|
||||||
ctx->add_statement (ret_var_stmt);
|
ctx->add_statement (ret_var_stmt);
|
||||||
ctx->push_fn (fndecl, return_address);
|
ctx->push_fn (fndecl, return_address, resolved_type);
|
||||||
|
|
||||||
if (is_block_expr)
|
if (is_block_expr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct fncontext
|
||||||
{
|
{
|
||||||
tree fndecl;
|
tree fndecl;
|
||||||
::Bvariable *ret_addr;
|
::Bvariable *ret_addr;
|
||||||
|
TyTy::BaseType *retty;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
|
@ -267,9 +268,9 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_fn (tree fn, ::Bvariable *ret_addr)
|
void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
|
||||||
{
|
{
|
||||||
fn_stack.push_back (fncontext{fn, ret_addr});
|
fn_stack.push_back (fncontext{fn, ret_addr, retty});
|
||||||
}
|
}
|
||||||
void pop_fn () { fn_stack.pop_back (); }
|
void pop_fn () { fn_stack.pop_back (); }
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,25 @@ CompileExpr::visit (HIR::ReturnExpr &expr)
|
||||||
tree return_value = expr.has_return_expr ()
|
tree return_value = expr.has_return_expr ()
|
||||||
? CompileExpr::Compile (expr.return_expr.get (), ctx)
|
? CompileExpr::Compile (expr.return_expr.get (), ctx)
|
||||||
: unit_expression (ctx, expr.get_locus ());
|
: unit_expression (ctx, expr.get_locus ());
|
||||||
|
|
||||||
|
if (expr.has_return_expr ())
|
||||||
|
{
|
||||||
|
HirId id = expr.get_mappings ().get_hirid ();
|
||||||
|
Location rvalue_locus = expr.return_expr->get_locus ();
|
||||||
|
|
||||||
|
TyTy::BaseType *expected = fncontext.retty;
|
||||||
|
Location lvalue_locus
|
||||||
|
= ctx->get_mappings ()->lookup_location (expected->get_ref ());
|
||||||
|
|
||||||
|
TyTy::BaseType *actual = nullptr;
|
||||||
|
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||||
|
expr.return_expr->get_mappings ().get_hirid (), &actual);
|
||||||
|
rust_assert (ok);
|
||||||
|
|
||||||
|
return_value = coercion_site (id, return_value, actual, expected,
|
||||||
|
lvalue_locus, rvalue_locus);
|
||||||
|
}
|
||||||
|
|
||||||
tree return_stmt
|
tree return_stmt
|
||||||
= ctx->get_backend ()->return_statement (fncontext.fndecl, return_value,
|
= ctx->get_backend ()->return_statement (fncontext.fndecl, return_value,
|
||||||
expr.get_locus ());
|
expr.get_locus ());
|
||||||
|
@ -2804,7 +2823,7 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
|
||||||
|
|
||||||
ctx->add_statement (ret_var_stmt);
|
ctx->add_statement (ret_var_stmt);
|
||||||
|
|
||||||
ctx->push_fn (fndecl, return_address);
|
ctx->push_fn (fndecl, return_address, tyret);
|
||||||
|
|
||||||
if (is_block_expr)
|
if (is_block_expr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,10 +164,9 @@ TypeCheckExpr::visit (HIR::ReturnExpr &expr)
|
||||||
? TypeCheckExpr::Resolve (expr.get_expr ())
|
? TypeCheckExpr::Resolve (expr.get_expr ())
|
||||||
: TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
|
: TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
|
||||||
|
|
||||||
infered = unify_site (expr.get_mappings ().get_hirid (),
|
coercion_site (expr.get_mappings ().get_hirid (),
|
||||||
TyTy::TyWithLocation (fn_return_tyty),
|
TyTy::TyWithLocation (fn_return_tyty),
|
||||||
TyTy::TyWithLocation (expr_ty, expr_locus),
|
TyTy::TyWithLocation (expr_ty, expr_locus), expr.get_locus ());
|
||||||
expr.get_locus ());
|
|
||||||
|
|
||||||
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
|
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
|
||||||
}
|
}
|
||||||
|
|
35
gcc/testsuite/rust/execute/torture/coercion3.rs
Normal file
35
gcc/testsuite/rust/execute/torture/coercion3.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// { dg-output "123\n" }
|
||||||
|
trait A {
|
||||||
|
fn get_int(&self) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl A for i32 {
|
||||||
|
fn get_int(&self) -> i32 {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_dyn_a(x: &i32) -> &dyn A {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clobber_stack() {
|
||||||
|
let _z: [usize; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn printf(s: *const i8, ...) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> i32 {
|
||||||
|
let x = 123;
|
||||||
|
let y = get_dyn_a(&x);
|
||||||
|
clobber_stack();
|
||||||
|
let value = y.get_int();
|
||||||
|
let fmt_string = "%d\n\0" as *const str as *const i8;
|
||||||
|
unsafe {
|
||||||
|
printf(fmt_string, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue