aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-08 15:51:54 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-09 09:47:35 +0000
commitb96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44 (patch)
treeec392cdf34bc5bdd5d9193745c4b0b48a4db8cbb
parent60cccd8e58f2a024676599cc00971a6e406e6d42 (diff)
downloadgcc-b96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44.zip
gcc-b96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44.tar.gz
gcc-b96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44.tar.bz2
Fix bad type resolution for CallExpr when fn is not simply PathInExpression
When we have a function that is for example a FieldAccessExpression the compiler must resolve and compile that field into a reference which can be called. This is not simple direct call to a function in that senario. Fixes #217
-rw-r--r--gcc/rust/backend/rust-compile.cc46
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h87
-rw-r--r--gcc/testsuite/rust.test/compilable/function_reference3.rs18
3 files changed, 69 insertions, 82 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 0b83c72..600b2f9 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -53,33 +53,9 @@ CompileCrate::go ()
void
CompileExpr::visit (HIR::CallExpr &expr)
{
- // this can be a function call or it can be a constructor for a tuple struct
- Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx);
- if (fn != nullptr)
+ Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx);
+ if (type != nullptr)
{
- std::vector<Bexpression *> args;
- expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
- Bexpression *compiled_expr = CompileExpr::Compile (p, ctx);
- rust_assert (compiled_expr != nullptr);
- args.push_back (compiled_expr);
- return true;
- });
-
- auto fncontext = ctx->peek_fn ();
- translated
- = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args,
- nullptr, expr.get_locus ());
- }
- else
- {
- Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx);
- if (type == nullptr)
- {
- rust_fatal_error (expr.get_locus (),
- "failed to lookup type associated with call");
- return;
- }
-
// this assumes all fields are in order from type resolution and if a base
// struct was specified those fields are filed via accesors
std::vector<Bexpression *> vals;
@@ -93,6 +69,24 @@ CompileExpr::visit (HIR::CallExpr &expr)
= ctx->get_backend ()->constructor_expression (type, vals,
expr.get_locus ());
}
+ else
+ {
+ // must be a call to a function
+ Bexpression *fn = CompileExpr::Compile (expr.get_fnexpr (), ctx);
+
+ std::vector<Bexpression *> args;
+ expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
+ Bexpression *compiled_expr = CompileExpr::Compile (p, ctx);
+ rust_assert (compiled_expr != nullptr);
+ args.push_back (compiled_expr);
+ return true;
+ });
+
+ auto fncontext = ctx->peek_fn ();
+ translated
+ = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args,
+ nullptr, expr.get_locus ());
+ }
}
void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 43e51c8..cb92332 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -155,58 +155,11 @@ public:
void visit (HIR::CallExpr &expr)
{
- auto fn = expr.get_fnexpr ();
- auto fn_node_id = fn->get_mappings ().get_nodeid ();
-
- // then lookup the reference_node_id
- NodeId ref_node_id = UNKNOWN_NODEID;
- if (resolver->lookup_resolved_name (fn_node_id, &ref_node_id))
- {
- Definition def;
- if (!resolver->lookup_definition (ref_node_id, &def))
- {
- rust_error_at (expr.get_locus (),
- "unknown reference for resolved name");
- return;
- }
- ref_node_id = def.parent;
- }
- else if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id))
- {
- rust_error_at (expr.get_locus (),
- "Failed to lookup type reference for node: %s",
- expr.as_string ().c_str ());
- return;
- }
-
- if (ref_node_id == UNKNOWN_NODEID)
- {
- rust_error_at (expr.get_locus (), "unresolved node: %s",
- expr.as_string ().c_str ());
- return;
- }
-
- // node back to HIR
- HirId ref;
- if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
- ref_node_id, &ref))
- {
- rust_error_at (expr.get_locus (), "reverse lookup failure for node %u",
- ref_node_id);
- return;
- }
-
- // check if this has a type
- TyTy::TyBase *lookup;
- if (!context->lookup_type (ref, &lookup))
- {
- rust_error_at (mappings->lookup_location (ref),
- "failed to lookup type for CallExpr: %s",
- expr.as_string ().c_str ());
- return;
- }
+ TyTy::TyBase *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ());
+ if (function_tyty == nullptr)
+ return;
- infered = TyTy::TypeCheckCallExpr::go (lookup, expr, context);
+ infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, context);
if (infered == nullptr)
{
rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr");
@@ -703,6 +656,10 @@ public:
void visit (HIR::GroupedExpr &expr)
{
+ printf ("inside grouped expr: \n%s\n inside it is: \n%s\n",
+ expr.as_string ().c_str (),
+ expr.get_expr_in_parens ()->as_string ().c_str ());
+
infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ());
}
@@ -738,16 +695,33 @@ public:
NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
// then lookup the reference_node_id
- NodeId ref_node_id;
- if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
{
- if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
+ // these ref_node_ids will resolve to a pattern declaration but we are
+ // interested in the definition that this refers to get the parent id
+ Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
{
rust_error_at (expr.get_locus (),
- "Failed to lookup reference for node: %s",
- expr.as_string ().c_str ());
+ "unknown reference for resolved name");
return;
}
+ ref_node_id = def.parent;
+ }
+ else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
+ {
+ rust_error_at (expr.get_locus (),
+ "Failed to lookup type reference for node: %s",
+ expr.as_string ().c_str ());
+ return;
+ }
+
+ if (ref_node_id == UNKNOWN_NODEID)
+ {
+ rust_error_at (expr.get_locus (), "unresolved node: %s",
+ expr.as_string ().c_str ());
+ return;
}
// node back to HIR
@@ -763,6 +737,7 @@ public:
{
rust_error_at (expr.get_locus (),
"failed to resolve PathInExpression type");
+ return;
}
}
diff --git a/gcc/testsuite/rust.test/compilable/function_reference3.rs b/gcc/testsuite/rust.test/compilable/function_reference3.rs
new file mode 100644
index 0000000..32f4728
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/function_reference3.rs
@@ -0,0 +1,18 @@
+struct Foo {
+ a: fn(i32) -> i32,
+ b: i32,
+}
+
+fn test(a: i32) -> i32 {
+ a + 1
+}
+
+fn main() {
+ let a = test(1);
+
+ let b: fn(i32) -> i32 = test;
+ let c = b(1);
+
+ let d = Foo { a: test, b: c };
+ let e = (d.a)(d.b);
+}