public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Support Closure calls as generic trait bounds Date: Sat, 22 Oct 2022 10:48:36 +0000 (GMT) [thread overview] Message-ID: <20221022104836.E6CA53858419@sourceware.org> (raw) https://gcc.gnu.org/g:05bd0555fa398c171acc22b6cfa1d5974202a5c7 commit 05bd0555fa398c171acc22b6cfa1d5974202a5c7 Author: Philip Herron <philip.herron@embecosm.com> 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::ClosureType *> (tyty); - - std::vector<tree> 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<Resolver::Adjustment> *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<tree> 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<Resolver::Adjustment> *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<tree> 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<tree> 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<Args> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn f<F: FnOnce(i32) -> 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 +}
reply other threads:[~2022-10-22 10:48 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20221022104836.E6CA53858419@sourceware.org \ --to=tschwinge@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).