diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-06-23 17:22:12 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-06-24 12:36:08 +0100 |
commit | 92a434a33904608f5659cf7b5d4df3d2a99bd5bd (patch) | |
tree | 02daa3d23d04cb9c950b15d5a7a94f171e1241db /gcc/rust/resolve | |
parent | 23e748d7a6855ce132299cfef9692ee9c681de59 (diff) | |
download | gcc-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.h | 55 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 5 |
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 ¶m : 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; } |