From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id E6CA53858419; Sat, 22 Oct 2022 10:48:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E6CA53858419 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1666435716; bh=Np3HBVjLLcWLVlz//V+BKFnDXO23tgwBdai/2QhGOe8=; h=From:To:Subject:Date:From; b=yptGx9E8ZYll4zkjCuHdBSJZUOySA/4s0KSEWInwYS4fm81xsAOkDgNA7OzRwcbg5 vlTpjTDGBZw92i/5ziZfhTJAxk47xSg3WYpQekGDY1oVumh3DJ+4uufqoxD4LNqEo+ Opw6tuZFKT5Umc8IZI3iLKhlmZP3Kqa9Y61Et5Zg= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Support Closure calls as generic trait bounds X-Act-Checkin: gcc X-Git-Author: Philip Herron X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: f6f87dead4bf2da20bc3a22dc6ca7a373c9ed05c X-Git-Newrev: 05bd0555fa398c171acc22b6cfa1d5974202a5c7 Message-Id: <20221022104836.E6CA53858419@sourceware.org> Date: Sat, 22 Oct 2022 10:48:36 +0000 (GMT) List-Id: https://gcc.gnu.org/g:05bd0555fa398c171acc22b6cfa1d5974202a5c7 commit 05bd0555fa398c171acc22b6cfa1d5974202a5c7 Author: Philip Herron Date: Thu Oct 20 18:31:02 2022 +0100 Support Closure calls as generic trait bounds Addresses #195 Diff: --- gcc/rust/backend/rust-compile-expr.cc | 116 +++++++++++++++---------- gcc/rust/backend/rust-compile-expr.h | 3 + gcc/testsuite/rust/execute/torture/closure2.rs | 32 +++++++ 3 files changed, 104 insertions(+), 47 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 738c7b10fa3..b077a12f7a3 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1693,53 +1693,10 @@ CompileExpr::visit (HIR::CallExpr &expr) auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx); // is this a closure call? - if (RS_CLOSURE_TYPE_P (TREE_TYPE (fn_address))) - { - rust_assert (tyty->get_kind () == TyTy::TypeKind::CLOSURE); - TyTy::ClosureType *closure = static_cast (tyty); - - std::vector tuple_arg_vals; - for (auto &argument : expr.get_arguments ()) - { - auto rvalue = CompileExpr::Compile (argument.get (), ctx); - tuple_arg_vals.push_back (rvalue); - } - - tree tuple_args_tyty - = TyTyResolveCompile::compile (ctx, &closure->get_parameters ()); - tree tuple_args - = ctx->get_backend ()->constructor_expression (tuple_args_tyty, false, - tuple_arg_vals, -1, - expr.get_locus ()); - - // need to apply any autoderef's to the self argument - HirId autoderef_mappings_id = expr.get_mappings ().get_hirid (); - std::vector *adjustments = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id, - &adjustments); - rust_assert (ok); - - // apply adjustments for the fn call - tree self - = resolve_adjustements (*adjustments, fn_address, expr.get_locus ()); - - // args are always self, and the tuple of the args we are passing where - // self is the path of the call-expr in this case the fn_address - std::vector args; - args.push_back (self); - args.push_back (tuple_args); - - // get the fn call address - tree closure_call_site = ctx->lookup_closure_decl (closure); - tree closure_call_address - = address_expression (closure_call_site, expr.get_locus ()); - translated - = ctx->get_backend ()->call_expression (closure_call_address, args, - nullptr /* static chain ?*/, - expr.get_locus ()); - return; - } + bool possible_trait_call + = generate_possible_fn_trait_call (expr, fn_address, &translated); + if (possible_trait_call) + return; bool is_varadic = false; if (tyty->get_kind () == TyTy::TypeKind::FNDEF) @@ -3068,5 +3025,70 @@ CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr, return TyTyResolveCompile::compile (ctx, item_tyty); } +bool +CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr, + tree receiver, tree *result) +{ + TyTy::FnType *fn_sig = nullptr; + bool found_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fn_sig); + if (!found_overload) + return false; + + auto id = fn_sig->get_ty_ref (); + auto dId = fn_sig->get_id (); + + tree function = error_mark_node; + bool found_closure = ctx->lookup_function_decl (id, &function, dId, fn_sig); + if (!found_closure) + { + // something went wrong we still return true as this was meant to be an fn + // trait call + *result = error_mark_node; + return true; + } + + // need to apply any autoderef's to the self argument + HirId autoderef_mappings_id = expr.get_mappings ().get_hirid (); + std::vector *adjustments = nullptr; + bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id, + &adjustments); + rust_assert (ok); + + // apply adjustments for the fn call + tree self = resolve_adjustements (*adjustments, receiver, expr.get_locus ()); + + // resolve the arguments + std::vector tuple_arg_vals; + for (auto &argument : expr.get_arguments ()) + { + auto rvalue = CompileExpr::Compile (argument.get (), ctx); + tuple_arg_vals.push_back (rvalue); + } + + // this is always the 2nd argument in the function signature + tree fnty = TREE_TYPE (function); + tree fn_arg_tys = TYPE_ARG_TYPES (fnty); + tree tuple_args_tyty_chain = TREE_CHAIN (fn_arg_tys); + tree tuple_args_tyty = TREE_VALUE (tuple_args_tyty_chain); + + tree tuple_args + = ctx->get_backend ()->constructor_expression (tuple_args_tyty, false, + tuple_arg_vals, -1, + expr.get_locus ()); + + // args are always self, and the tuple of the args we are passing where + // self is the path of the call-expr in this case the fn_address + std::vector args; + args.push_back (self); + args.push_back (tuple_args); + + tree call_address = address_expression (function, expr.get_locus ()); + *result = ctx->get_backend ()->call_expression (call_address, args, + nullptr /* static chain ?*/, + expr.get_locus ()); + return true; +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 6938c936240..a259daf0d69 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -152,6 +152,9 @@ protected: tree compiled_closure_tyty, TyTy::FnType **fn_tyty); + bool generate_possible_fn_trait_call (HIR::CallExpr &expr, tree receiver, + tree *result); + private: CompileExpr (Context *ctx); diff --git a/gcc/testsuite/rust/execute/torture/closure2.rs b/gcc/testsuite/rust/execute/torture/closure2.rs new file mode 100644 index 00000000000..45b3b5ce8b4 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/closure2.rs @@ -0,0 +1,32 @@ +// { dg-output "3\n" } +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn f i32>(g: F) { + let call = g(1); + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, call); + } +} + +pub fn main() -> i32 { + let a = |i: i32| { + let b = i + 2; + b + }; + f(a); + 0 +}