aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-06-23 17:22:12 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-06-24 12:36:08 +0100
commit92a434a33904608f5659cf7b5d4df3d2a99bd5bd (patch)
tree02daa3d23d04cb9c950b15d5a7a94f171e1241db /gcc/rust/resolve
parent23e748d7a6855ce132299cfef9692ee9c681de59 (diff)
downloadgcc-92a434a33904608f5659cf7b5d4df3d2a99bd5bd.zip
gcc-92a434a33904608f5659cf7b5d4df3d2a99bd5bd.tar.gz
gcc-92a434a33904608f5659cf7b5d4df3d2a99bd5bd.tar.bz2
Add support for nested functions
We missed that stmts in rust can be items like functions. This adds support for resolution and compilation of nested functions. Rust allows nested functions which are distinct to closures. Nested functions are not allowed to encapsulate the enclosing scope so they can be extracted as normal functions.
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h55
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc5
2 files changed, 57 insertions, 3 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 3fd1cfa..e68e7b9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -129,6 +129,61 @@ public:
resolver->get_type_scope ().pop ();
}
+ void visit (AST::Function &function) override
+ {
+ auto path = ResolveFunctionItemToCanonicalPath::resolve (function);
+ resolver->get_name_scope ().insert (
+ path, function.get_node_id (), function.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (function.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ resolver->insert_new_definition (function.get_node_id (),
+ Definition{function.get_node_id (),
+ function.get_node_id ()});
+
+ NodeId scope_node_id = function.get_node_id ();
+ resolver->get_name_scope ().push (scope_node_id);
+ resolver->get_type_scope ().push (scope_node_id);
+ resolver->get_label_scope ().push (scope_node_id);
+ resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
+ resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
+ resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+
+ if (function.has_generics ())
+ {
+ for (auto &generic : function.get_generic_params ())
+ ResolveGenericParam::go (generic.get (), function.get_node_id ());
+ }
+
+ if (function.has_return_type ())
+ ResolveType::go (function.get_return_type ().get (),
+ function.get_node_id ());
+
+ // we make a new scope so the names of parameters are resolved and shadowed
+ // correctly
+ for (auto &param : function.get_function_params ())
+ {
+ ResolveType::go (param.get_type ().get (), param.get_node_id ());
+ PatternDeclaration::go (param.get_pattern ().get (),
+ param.get_node_id ());
+
+ // the mutability checker needs to verify for immutable decls the number
+ // of assignments are <1. This marks an implicit assignment
+ resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (),
+ param.get_node_id ());
+ }
+
+ // resolve the function body
+ ResolveExpr::go (function.get_definition ().get (),
+ function.get_node_id ());
+
+ resolver->get_name_scope ().pop ();
+ resolver->get_type_scope ().pop ();
+ resolver->get_label_scope ().pop ();
+ }
+
private:
ResolveStmt (NodeId parent) : ResolverBase (parent) {}
};
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index e03a745..fae3f77 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -499,9 +499,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
else
{
rust_error_at (expr->get_locus (),
- "unknown root segment in path %s lookup %s",
- expr->as_string ().c_str (),
- root_ident_seg.as_string ().c_str ());
+ "Cannot find path %<%s%> in this scope",
+ expr->as_string ().c_str ());
return;
}