aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-type.h4
-rw-r--r--gcc/rust/backend/rust-compile-expr.h28
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc32
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h51
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h34
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h22
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h9
-rw-r--r--gcc/rust/rust-session-manager.cc4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h56
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h28
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h46
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc7
-rw-r--r--gcc/testsuite/rust.test/compilable/function_reference1.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/function_reference2.rs8
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 &param : 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 &param : 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 &param : 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);
+}