public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Support Closure calls as generic trait bounds
@ 2022-10-22 10:48 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-10-22 10:48 UTC (permalink / raw)
To: gcc-cvs
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
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-10-22 10:48 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-22 10:48 [gcc/devel/rust/master] Support Closure calls as generic trait bounds Thomas Schwinge
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).