diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-10-21 14:13:47 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-21 14:13:47 +0000 |
commit | 490aa25d5564313c1957bf28533fe902a0aaa1f2 (patch) | |
tree | 3fee40077e3efdb231b96772bd58c02522ce6f3a /gcc/rust/resolve | |
parent | 60b21d2f58f46c93fc33f6192682abfed62d8dd9 (diff) | |
parent | 05bd0555fa398c171acc22b6cfa1d5974202a5c7 (diff) | |
download | gcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.zip gcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.tar.gz gcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.tar.bz2 |
Merge #1608
1608: Initial support for closures r=philberty a=philberty
This patch series introduces initial support for closures. Rust's implementation
of closures is actually pretty clever, the function signatures for closures is driven
by the specific FnTrait that the closure implements, this means a CallExpr to a closure
becomes a method-call expr with the receiver type being the closure itself using the
normal autoderef mechanism to do method selection for an implicit impl block.
See https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71
The other implicit part of this is that arguments being passed to a closure _must_
be passed as a tuple. The down side of allowing libcore to specify the signatures
of the closure functions is that we are limited in how we pass arguments, but
using a tuple and then using similar machinery from the match-expr to restructure
the parameter access to become the tuple accessors makes it look seamless. For
example:
```rust
let closure_annotated = |i: i32| -> i32 { i + 123 };
let i = 1;
closure_annotated(i);
```
Wil generate a function and call-expr such as:
```c
i32 test::main::{{closure}} (struct {{closure}} $closure, struct (i32) args)
{
_1 = args.__0; // this is 'i'
return _1 + 123;
}
__attribute__((cdecl))
i32 test::main ()
{
struct
{
i32 __0;
} D.137;
i32 D.140;
const i32 a;
const struct{{closure}} closure_annotated;
const i32 i;
try
{
a = 1;
i = 1;
D.137.__0 = i;
_1 = test::main::{{closure}} (closure_annotated, D.137);
<...>
}
finally
{
closure_annotated = {CLOBBER(eol)};
}
}
```
Note this patch series does not implement the argument capture yet but this patch set is
good start to the implementation so far.
Addresses #195
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.cc | 58 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 48 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.cc | 15 |
3 files changed, 77 insertions, 44 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 4cc4e26..60b3eba 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -565,6 +565,64 @@ ResolveExpr::visit (AST::RangeFromToInclExpr &expr) ResolveExpr::go (expr.get_to_expr ().get (), prefix, canonical_prefix); } +void +ResolveExpr::visit (AST::ClosureExprInner &expr) +{ + NodeId scope_node_id = expr.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 ()); + + for (auto &p : expr.get_params ()) + { + resolve_closure_param (p); + } + + ResolveExpr::go (expr.get_definition_expr ().get (), prefix, + canonical_prefix); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); +} + +void +ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) +{ + NodeId scope_node_id = expr.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 ()); + + for (auto &p : expr.get_params ()) + { + resolve_closure_param (p); + } + + ResolveType::go (expr.get_return_type ().get ()); + ResolveExpr::go (expr.get_definition_block ().get (), prefix, + canonical_prefix); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); +} + +void +ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m) +{ + PatternDeclaration::go (param.get_pattern ().get ()); + + if (param.has_type_given ()) + ResolveType::go (param.get_type ().get ()); +} + ResolveExpr::ResolveExpr (const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 11a846a..c11718e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -34,90 +34,52 @@ public: const CanonicalPath &canonical_prefix); void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::PathInExpression &expr) override; - void visit (AST::QualifiedPathInExpression &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::IdentifierExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfExprConseqIf &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::ArrayElemsCopied &elems) override; - - // this this an empty struct constructor like 'S {}' void visit (AST::StructExprStruct &struct_expr) override; - - // this this a struct constructor with fields void visit (AST::StructExprStructFields &struct_expr) override; - void visit (AST::GroupedExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; + void visit (AST::ClosureExprInner &expr) override; + void visit (AST::ClosureExprInnerTyped &expr) override; + +protected: + void resolve_closure_param (AST::ClosureParam ¶m); private: ResolveExpr (const CanonicalPath &prefix, diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 6b08613..e42bab6 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -149,7 +149,20 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) break; case AST::TypePathSegment::SegmentType::FUNCTION: - gcc_unreachable (); + AST::TypePathSegmentFunction *fnseg + = static_cast<AST::TypePathSegmentFunction *> (segment.get ()); + + AST::TypePathFunction &fn = fnseg->get_type_path_function (); + for (auto ¶m : fn.get_params ()) + { + ResolveType::go (param.get ()); + } + + if (fn.has_return_type ()) + { + ResolveType::go (fn.get_return_type ().get ()); + } + break; } |