diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-type.h | 4 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 28 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-resolve-path.cc | 32 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-type.h | 51 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-type.h | 34 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 22 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 3 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 9 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 4 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 56 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 28 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-rules.h | 46 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 7 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/function_reference1.rs | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/function_reference2.rs | 8 |
15 files changed, 292 insertions, 48 deletions
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 0dfeb07..a9e0f0f 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -816,6 +816,10 @@ public: rust_assert (param_type != nullptr); return param_type; } + + ParamKind get_param_kind () const { return param_kind; } + + Identifier get_name () const { return name; } }; /* A function pointer type - can be created via coercion from function items and diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 7c2f32d..81d7786 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -127,20 +127,28 @@ public: return; } - // this could be a constant reference - if (ctx->lookup_const_decl (ref, &translated)) - return; - - // must be an identifier + Bfunction *fn = nullptr; Bvariable *var = nullptr; - if (!ctx->lookup_var_decl (ref, &var)) + if (ctx->lookup_const_decl (ref, &translated)) { - rust_fatal_error (expr.get_locus (), - "failed to lookup compiled variable"); return; } - - translated = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + else if (ctx->lookup_function_decl (ref, &fn)) + { + translated + = ctx->get_backend ()->function_code_expression (fn, + expr.get_locus ()); + } + else if (ctx->lookup_var_decl (ref, &var)) + { + translated + = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + } + else + { + rust_fatal_error (expr.get_locus (), + "failed to lookup compiled reference"); + } } void visit (HIR::LiteralExpr &expr) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 37285b7..818d5cb 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -28,23 +28,43 @@ void ResolvePathRef::visit (HIR::PathInExpression &expr) { // need to look up the reference for this identifier - NodeId ref_node_id; - if (!ctx->get_resolver ()->lookup_resolved_name ( + NodeId ref_node_id = UNKNOWN_NODEID; + if (ctx->get_resolver ()->lookup_resolved_name ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - return; + Resolver::Definition def; + if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return; + } + ref_node_id = def.parent; } + // this can fail because it might be a Constructor for something + // in that case the caller should attempt ResolvePathType::Compile + if (ref_node_id == UNKNOWN_NODEID) + return; + HirId ref; if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_error_at (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse call path lookup failure"); return; } - // assumes paths are functions for now - Bfunction *fn; + // this might be a variable reference or a function reference + Bvariable *var = nullptr; + if (ctx->lookup_var_decl (ref, &var)) + { + resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + return; + } + + // must be a function call + Bfunction *fn = nullptr; if (!ctx->lookup_function_decl (ref, &fn)) { // this might fail because its a forward decl so we can attempt to diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 84d09bc..e78ae5a 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -42,6 +42,57 @@ public: return resolver.translated; } + void visit (AST::BareFunctionType &fntype) + { + bool is_variadic = false; + std::vector<HIR::LifetimeParam> lifetime_params; + HIR::FunctionQualifiers qualifiers ( + HIR::FunctionQualifiers::AsyncConstStatus::NONE, false); + + std::vector<HIR::MaybeNamedParam> named_params; + for (auto ¶m : fntype.get_function_params ()) + { + HIR::MaybeNamedParam::ParamKind kind; + switch (param.get_param_kind ()) + { + case AST::MaybeNamedParam::ParamKind::UNNAMED: + kind = HIR::MaybeNamedParam::ParamKind::UNNAMED; + break; + case AST::MaybeNamedParam::ParamKind::IDENTIFIER: + kind = HIR::MaybeNamedParam::ParamKind::IDENTIFIER; + break; + case AST::MaybeNamedParam::ParamKind::WILDCARD: + kind = HIR::MaybeNamedParam::ParamKind::WILDCARD; + break; + } + + HIR::Type *param_type + = ASTLoweringType::translate (param.get_type ().get ()); + + HIR::MaybeNamedParam p (param.get_name (), kind, + std::unique_ptr<HIR::Type> (param_type), + param.get_locus ()); + named_params.push_back (std::move (p)); + } + + HIR::Type *return_type = nullptr; + if (fntype.has_return_type ()) + { + return_type + = ASTLoweringType::translate (fntype.get_return_type ().get ()); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, fntype.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::BareFunctionType ( + std::move (mapping), std::move (lifetime_params), std::move (qualifiers), + std::move (named_params), is_variadic, + std::unique_ptr<HIR::Type> (return_type), fntype.get_locus ()); + } + void visit (AST::TupleType &tuple) { std::vector<std::unique_ptr<HIR::Type> > elems; diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index fc369c3..ebed119 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -791,6 +791,16 @@ public: } Location get_locus () const { return locus; } + + std::unique_ptr<Type> &get_type () + { + rust_assert (param_type != nullptr); + return param_type; + } + + ParamKind get_param_kind () const { return param_kind; } + + Identifier get_name () const { return name; } }; /* A function pointer type - can be created via coercion from function items and @@ -805,9 +815,7 @@ class BareFunctionType : public TypeNoBounds std::vector<MaybeNamedParam> params; bool is_variadic; - // bool has_return_type; - // BareFunctionReturnType return_type; - std::unique_ptr<TypeNoBounds> return_type; // inlined version + std::unique_ptr<Type> return_type; // inlined version Location locus; @@ -822,7 +830,7 @@ public: std::vector<LifetimeParam> lifetime_params, FunctionQualifiers qualifiers, std::vector<MaybeNamedParam> named_params, bool is_variadic, - std::unique_ptr<TypeNoBounds> type, Location locus) + std::unique_ptr<Type> type, Location locus) : TypeNoBounds (mappings), for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), @@ -834,8 +842,7 @@ public: : TypeNoBounds (other.mappings), for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), is_variadic (other.is_variadic), - return_type (other.return_type->clone_type_no_bounds ()), - locus (other.locus) + return_type (other.return_type->clone_type ()), locus (other.locus) {} // Overload assignment operator to deep copy @@ -846,7 +853,7 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds (); + return_type = other.return_type->clone_type (); locus = other.locus; return *this; @@ -862,6 +869,19 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector<MaybeNamedParam> &get_function_params () { return params; } + const std::vector<MaybeNamedParam> &get_function_params () const + { + return params; + } + + // TODO: would a "vis_type" be better? + std::unique_ptr<Type> &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 9366818..f62f17c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -102,16 +102,26 @@ public: void visit (AST::IdentifierExpr &expr) { - if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), + parent}); + } + else if (resolver->get_type_scope ().lookup (expr.as_string (), + &resolved_node)) + { + resolver->insert_resolved_type (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), + parent}); + } + else { rust_error_at (expr.get_locus (), "failed to find name: %s", expr.as_string ().c_str ()); - return; } - - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), parent}); } void visit (AST::ArithmeticOrLogicalExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 90f9cd6..c3f5e4c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -75,6 +75,9 @@ public: resolver->get_name_scope ().insert (function.get_function_name (), function.get_node_id (), function.get_locus ()); + resolver->insert_new_definition (function.get_node_id (), + Definition{function.get_node_id (), + function.get_node_id ()}); // if this does not get a reference it will be determined to be unused // lets give it a fake reference to itself diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 20fb0b6..b303ee9 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -34,6 +34,15 @@ public: type->accept_vis (resolver); }; + void visit (AST::BareFunctionType &fntype) + { + for (auto ¶m : fntype.get_function_params ()) + ResolveType::go (param.get_type ().get (), fntype.get_node_id ()); + + if (fntype.has_return_type ()) + ResolveType::go (fntype.get_return_type ().get (), fntype.get_node_id ()); + } + void visit (AST::TupleType &tuple) { if (tuple.is_unit_type ()) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 281049d..afc238b 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -550,8 +550,8 @@ Session::parse_file (const char *filename) type_resolution (hir); // FIXME this needs an option of itself - // auto buf = Resolver::TypeResolverDump::go (hir); - // fprintf (stderr, "%s\n", buf.c_str ()); + auto buf = Resolver::TypeResolverDump::go (hir); + fprintf (stderr, "%s\n", buf.c_str ()); if (saw_errors ()) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 17f1611..78f0d0d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -157,17 +157,32 @@ public: auto fn = expr.get_fnexpr (); auto fn_node_id = fn->get_mappings ().get_nodeid (); - // CallExpr might be a function but it might also be a TupleStruct - NodeId ref_node_id; - if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) { - if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_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 (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 @@ -258,28 +273,39 @@ 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)) + { + // 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 (), + "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 reference for node: %s", + "Failed to lookup type reference for node: %s", expr.as_string ().c_str ()); return; } - // 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)) + if (ref_node_id == UNKNOWN_NODEID) { - rust_error_at (expr.get_locus (), "unknown reference"); + 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 (), - def.parent, &ref)) + ref_node_id, &ref)) { rust_error_at (expr.get_locus (), "reverse lookup failure"); return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index e5d3898..2894899 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -79,6 +79,34 @@ public: return resolver.translated; } + void visit (HIR::BareFunctionType &fntype) + { + TyTy::TyBase *return_type + = fntype.has_return_type () + ? TypeCheckType::Resolve (fntype.get_return_type ().get ()) + : new TyTy::UnitType (fntype.get_mappings ().get_hirid ()); + + std::vector<std::pair<HIR::Pattern *, TyTy::TyBase *> > params; + for (auto ¶m : fntype.get_function_params ()) + { + std::unique_ptr<HIR::Pattern> to_bind; + + bool is_ref = false; + bool is_mut = false; + + HIR::Pattern *pattern + = new HIR::IdentifierPattern (param.get_name (), param.get_locus (), + is_ref, is_mut, std::move (to_bind)); + + TyTy::TyBase *ptype = TypeCheckType::Resolve (param.get_type ().get ()); + params.push_back ( + std::pair<HIR::Pattern *, TyTy::TyBase *> (pattern, ptype)); + } + + translated = new TyTy::FnType (fntype.get_mappings ().get_hirid (), + std::move (params), return_type); + } + void visit (HIR::TupleType &tuple) { if (tuple.is_unit_type ()) diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index e17cec7..be58805 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -410,6 +410,52 @@ class FnRules : public BaseRules public: FnRules (FnType *base) : BaseRules (base), base (base) {} + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (FnType &type) override + { + if (base->num_params () != type.num_params ()) + { + BaseRules::visit (type); + return; + } + + // FIXME add an abstract method for is_equal on TyBase + for (size_t i = 0; i < base->num_params (); i++) + { + auto a = base->param_at (i).second; + auto b = type.param_at (i).second; + + auto combined_param = a->combine (b); + if (combined_param == nullptr) + { + BaseRules::visit (type); + return; + } + } + + auto combined_return + = base->get_return_type ()->combine (type.get_return_type ()); + if (combined_return == nullptr) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + private: FnType *base; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 249e876..d506415 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -147,11 +147,14 @@ ADTType::accept_vis (TyVisitor &vis) std::string ADTType::as_string () const { + if (num_fields () == 0) + return identifier; + std::string fields_buffer; for (auto &field : fields) - fields_buffer += field->as_string () + "\n"; + fields_buffer += field->as_string () + ", "; - return identifier + "{\n" + fields_buffer + "\n}"; + return identifier + "{" + fields_buffer + "}"; } TyBase * diff --git a/gcc/testsuite/rust.test/compilable/function_reference1.rs b/gcc/testsuite/rust.test/compilable/function_reference1.rs new file mode 100644 index 0000000..604bad0 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/function_reference1.rs @@ -0,0 +1,8 @@ +fn test(a: i32) -> i32 { + a + 1 +} + +fn main() { + let a = test; + let b = a(1); +} diff --git a/gcc/testsuite/rust.test/compilable/function_reference2.rs b/gcc/testsuite/rust.test/compilable/function_reference2.rs new file mode 100644 index 0000000..0b963b2 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/function_reference2.rs @@ -0,0 +1,8 @@ +fn test(a: i32) -> i32 { + a + 1 +} + +fn main() { + let a: fn(i32) -> i32 = test; + let b = a(1); +} |