From b96299b0b96b6714d5a7b03fa6d4f1ea7d09fc44 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 8 Feb 2021 15:51:54 +0000 Subject: 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 --- gcc/rust/backend/rust-compile.cc | 46 +++++------- gcc/rust/typecheck/rust-hir-type-check-expr.h | 87 ++++++++-------------- .../rust.test/compilable/function_reference3.rs | 18 +++++ 3 files changed, 69 insertions(+), 82 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/function_reference3.rs (limited to 'gcc') 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 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 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 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); +} -- cgit v1.1