aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorYap Zhi Heng <yapzhhg@gmail.com>2025-07-30 23:37:43 +0800
committerArthur Cohen <arthur.cohen@embecosm.com>2025-08-05 16:37:01 +0200
commita22c11304c40ed8895d00555fe91a33291ba7c67 (patch)
tree52c77d6b41b7a6f3510c8951ac551b45db4ba8b8 /gcc/rust
parentad8393db6b492358028367d27b4f3b918dd7a7c0 (diff)
downloadgcc-a22c11304c40ed8895d00555fe91a33291ba7c67.zip
gcc-a22c11304c40ed8895d00555fe91a33291ba7c67.tar.gz
gcc-a22c11304c40ed8895d00555fe91a33291ba7c67.tar.bz2
gccrs: Add rest pattern support for AST::SlicePattern
The main change can be found in ast/rust-pattern.h, which introduces 2 item types for AST::SlicePattern - one without rest pattern (SlicePatternItemsNoRest) & the other with it (SlicePatternItemsHasRest). This led to a number of cascading changes as seen in the changelog. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc: Add support for the 2 new classes. * ast/rust-ast-collector.h: Header file update for above. * ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes. * ast/rust-ast-visitor.cc: Add visit support for the 2 new classes. * ast/rust-ast-visitor.h: Header file update for above. * ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes. * ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold 2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest. * expand/rust-cfg-strip.cc: Add support for the 2 new classes. * expand/rust-cfg-strip.h: Header file update for above. * expand/rust-derive.h: Add visits for the 2 new classes. * hir/rust-ast-lower-base.cc: Add visits for the 2 new classes. * hir/rust-ast-lower-base.h: Header file update for above. * hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support SlicePatternItemsNoRest. * parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into respective SlicePatternItems. * resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes. * resolve/rust-ast-resolve-base.h: Header file update for above. * resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new classes. Signed-off-by: Yap Zhi Heng <yapzhhg@gmail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc26
-rw-r--r--gcc/rust/ast/rust-ast-collector.h2
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h2
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc19
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h4
-rw-r--r--gcc/rust/ast/rust-pattern.cc54
-rw-r--r--gcc/rust/ast/rust-pattern.h204
-rw-r--r--gcc/rust/expand/rust-cfg-strip.cc36
-rw-r--r--gcc/rust/expand/rust-cfg-strip.h2
-rw-r--r--gcc/rust/expand/rust-derive.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc6
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc23
-rw-r--r--gcc/rust/parse/rust-parse-impl.h72
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc8
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc25
17 files changed, 447 insertions, 42 deletions
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index b27a3af..677c247 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -2718,10 +2718,34 @@ TokenCollector::visit (GroupedPattern &pattern)
}
void
+TokenCollector::visit (SlicePatternItemsNoRest &items)
+{
+ visit_items_joined_by_separator (items.get_patterns (), COMMA);
+}
+
+void
+TokenCollector::visit (SlicePatternItemsHasRest &items)
+{
+ if (!items.get_lower_patterns ().empty ())
+ {
+ visit_items_joined_by_separator (items.get_lower_patterns (), COMMA);
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ }
+
+ push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
+
+ if (!items.get_upper_patterns ().empty ())
+ {
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ visit_items_joined_by_separator (items.get_upper_patterns (), COMMA);
+ }
+}
+
+void
TokenCollector::visit (SlicePattern &pattern)
{
push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ()));
- visit_items_joined_by_separator (pattern.get_items (), COMMA);
+ visit (pattern.get_items ());
push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
}
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index 767d211..9ffbfce 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -378,6 +378,8 @@ public:
void visit (TuplePatternItemsRanged &tuple_items);
void visit (TuplePattern &pattern);
void visit (GroupedPattern &pattern);
+ void visit (SlicePatternItemsNoRest &items);
+ void visit (SlicePatternItemsHasRest &items);
void visit (SlicePattern &pattern);
void visit (AltPattern &pattern);
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index eb1f3ea..1dfb25c 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -248,6 +248,8 @@ class TuplePatternItemsMultiple;
class TuplePatternItemsRanged;
class TuplePattern;
class GroupedPattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index f752b3a..88dc24b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -1347,13 +1347,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items)
{
- for (auto &item : pattern.get_items ())
+ for (auto &item : items.get_patterns ())
+ visit (item);
+}
+
+void
+DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+ for (auto &item : items.get_lower_patterns ())
+ visit (item);
+ for (auto &item : items.get_upper_patterns ())
visit (item);
}
void
+DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
DefaultASTVisitor::visit (AST::AltPattern &pattern)
{
for (auto &alt : pattern.get_alts ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 020400d..a5469cc 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -212,6 +212,8 @@ public:
virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
virtual void visit (TuplePattern &pattern) = 0;
virtual void visit (GroupedPattern &pattern) = 0;
+ virtual void visit (SlicePatternItemsNoRest &items) = 0;
+ virtual void visit (SlicePatternItemsHasRest &items) = 0;
virtual void visit (SlicePattern &pattern) = 0;
virtual void visit (AltPattern &pattern) = 0;
@@ -386,6 +388,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
virtual void visit (AST::EmptyStmt &stmt) override;
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index 62bf6f2..15ab0b7 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -327,17 +327,53 @@ GroupedExpr::as_string () const
}
std::string
-SlicePattern::as_string () const
+SlicePatternItemsNoRest::as_string () const
{
- std::string str ("SlicePattern: ");
+ std::string str;
- for (const auto &pattern : items)
+ for (const auto &pattern : patterns)
str += "\n " + pattern->as_string ();
return str;
}
std::string
+SlicePatternItemsHasRest::as_string () const
+{
+ std::string str;
+
+ str += "\n Lower patterns: ";
+ if (lower_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &lower : lower_patterns)
+ str += "\n " + lower->as_string ();
+ }
+
+ str += "\n Upper patterns: ";
+ if (upper_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &upper : upper_patterns)
+ str += "\n " + upper->as_string ();
+ }
+
+ return str;
+}
+
+std::string
+SlicePattern::as_string () const
+{
+ return "SlicePattern: " + items->as_string ();
+}
+
+std::string
AltPattern::as_string () const
{
std::string str ("AltPattern: ");
@@ -367,6 +403,18 @@ GroupedExpr::accept_vis (ASTVisitor &vis)
}
void
+SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
SlicePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 57c065f..4945ec4 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -1521,41 +1521,217 @@ protected:
}
};
+// Base abstract class representing patterns in a SlicePattern
+class SlicePatternItems
+{
+public:
+ enum SlicePatternItemType
+ {
+ NO_REST,
+ HAS_REST,
+ };
+
+ virtual ~SlicePatternItems () {}
+
+ // TODO: should this store location data?
+
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (
+ clone_slice_pattern_items_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual SlicePatternItemType get_pattern_type () const = 0;
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0;
+};
+
+// Class representing the patterns in a SlicePattern without `..`
+class SlicePatternItemsNoRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> patterns;
+
+public:
+ SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
+ : patterns (std::move (patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
+ {
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to vector clone
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
+ {
+ patterns.clear ();
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
+ {
+ return patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::NO_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsNoRest (*this);
+ }
+};
+
+// Class representing the patterns in a SlicePattern that contains a `..`
+class SlicePatternItemsHasRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
+
+public:
+ SlicePatternItemsHasRest (
+ std::vector<std::unique_ptr<Pattern>> lower_patterns,
+ std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ : lower_patterns (std::move (lower_patterns)),
+ upper_patterns (std::move (upper_patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to clone
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.clear ();
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.clear ();
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::HAS_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsHasRest (*this);
+ }
+};
+
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern>> items;
+ std::unique_ptr<SlicePatternItems> items;
location_t locus;
NodeId node_id;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+ SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- // Copy constructor with vector clone
+ // Copy constructor requires clone
SlicePattern (SlicePattern const &other) : locus (other.locus)
{
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+
node_id = other.node_id;
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ items = other.items->clone_slice_pattern_items ();
}
- // Overloaded assignment operator to vector clone
+ // Overloaded assignment operator to clone
SlicePattern &operator= (SlicePattern const &other)
{
locus = other.locus;
node_id = other.node_id;
- items.clear ();
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+ items = other.items->clone_slice_pattern_items ();
return *this;
}
@@ -1568,10 +1744,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
- const std::vector<std::unique_ptr<Pattern>> &get_items () const
+ SlicePatternItems &get_items ()
{
- return items;
+ rust_assert (items != nullptr);
+ return *items;
}
NodeId get_node_id () const override { return node_id; }
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index ac795f7..58d8071 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -2478,20 +2478,44 @@ CfgStrip::visit (AST::GroupedPattern &pattern)
}
void
-CfgStrip::visit (AST::SlicePattern &pattern)
+CfgStrip::visit (AST::SlicePatternItemsNoRest &items)
{
- AST::DefaultASTVisitor::visit (pattern);
+ AST::DefaultASTVisitor::visit (items);
// can't strip individual patterns, only sub-patterns
- for (auto &item : pattern.get_items ())
+ for (auto &pattern : items.get_patterns ())
{
- if (item->is_marked_for_strip ())
- rust_error_at (item->get_locus (),
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
"cannot strip pattern in this position");
- // TODO: quit stripping now? or keep going?
}
}
void
+CfgStrip::visit (AST::SlicePatternItemsHasRest &items)
+{
+ AST::DefaultASTVisitor::visit (items);
+ // can't strip individual patterns, only sub-patterns
+ for (auto &pattern : items.get_lower_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+ for (auto &pattern : items.get_upper_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+}
+
+void
+CfgStrip::visit (AST::SlicePattern &pattern)
+{
+ AST::DefaultASTVisitor::visit (pattern);
+}
+
+void
CfgStrip::visit (AST::AltPattern &pattern)
{
AST::DefaultASTVisitor::visit (pattern);
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index 4900ae8..767cf28 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -172,6 +172,8 @@ public:
void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
void visit (AST::TuplePatternItemsRanged &tuple_items) override;
void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePatternItemsNoRest &items) override;
+ void visit (AST::SlicePatternItemsHasRest &items) override;
void visit (AST::SlicePattern &pattern) override;
void visit (AST::AltPattern &pattern) override;
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 297d079..283b443 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -231,6 +231,8 @@ private:
virtual void visit (TuplePatternItemsRanged &tuple_items) override final{};
virtual void visit (TuplePattern &pattern) override final{};
virtual void visit (GroupedPattern &pattern) override final{};
+ virtual void visit (SlicePatternItemsNoRest &items) override final{};
+ virtual void visit (SlicePatternItemsHasRest &items) override final{};
virtual void visit (SlicePattern &pattern) override final{};
virtual void visit (AltPattern &pattern) override final{};
virtual void visit (EmptyStmt &stmt) override final{};
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 9098a9f..09f4b93 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -495,6 +495,12 @@ void
ASTLoweringBase::visit (AST::GroupedPattern &)
{}
void
+ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+void
+ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+void
ASTLoweringBase::visit (AST::SlicePattern &)
{}
void
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 6437b2e..af21c40 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -236,6 +236,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index bb5b93b..b9d7b62 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -321,10 +321,27 @@ void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
std::vector<std::unique_ptr<HIR::Pattern>> items;
- for (auto &p : pattern.get_items ())
+
+ switch (pattern.get_items ().get_pattern_type ())
{
- HIR::Pattern *item = ASTLoweringPattern::translate (*p);
- items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ AST::SlicePatternItemsNoRest &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &p : ref.get_patterns ())
+ {
+ HIR::Pattern *item = ASTLoweringPattern::translate (*p);
+ items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ }
+ }
+ break;
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ rust_error_at (pattern.get_locus (),
+ "lowering of slice patterns with rest elements are not "
+ "supported yet");
+ }
+ break;
}
auto crate_num = mappings.get_current_crate ();
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 6d996ca..80b529c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -10962,27 +10962,47 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
{
location_t square_locus = lexer.peek_token ()->get_locus ();
std::vector<std::unique_ptr<AST::Pattern>> patterns;
+ tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns
+ = tl::nullopt;
+
+ // lambda function to determine which vector to push new patterns into
+ auto get_pattern_ref
+ = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & {
+ return upper_patterns.has_value () ? upper_patterns.value () : patterns;
+ };
+
skip_token (LEFT_SQUARE);
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
{
skip_token (RIGHT_SQUARE);
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
// parse initial pattern (required)
- std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
- if (initial_pattern == nullptr)
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
{
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse initial pattern in slice pattern");
- add_error (std::move (error));
-
- return nullptr;
+ lexer.skip_token ();
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
}
+ else
+ {
+ // Not a rest pattern `..`, parse normally
+ std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
+ if (initial_pattern == nullptr)
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "failed to parse initial pattern in slice pattern");
+ add_error (std::move (error));
- patterns.push_back (std::move (initial_pattern));
+ return nullptr;
+ }
+
+ patterns.push_back (std::move (initial_pattern));
+ }
const_TokenPtr t = lexer.peek_token ();
while (t->get_id () == COMMA)
@@ -10993,6 +11013,23 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
break;
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
+ {
+ if (upper_patterns.has_value ())
+ {
+ // DOT_DOT has been parsed before
+ Error error (lexer.peek_token ()->get_locus (), "%s",
+ "`..` can only be used once per slice pattern");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
+ lexer.skip_token ();
+ t = lexer.peek_token ();
+ continue;
+ }
+
// parse pattern (required)
std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
if (pattern == nullptr)
@@ -11003,7 +11040,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
- patterns.push_back (std::move (pattern));
+ get_pattern_ref ().push_back (std::move (pattern));
t = lexer.peek_token ();
}
@@ -11013,8 +11050,21 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
+ if (upper_patterns.has_value ())
+ {
+ // Slice pattern with rest
+ std::unique_ptr<AST::SlicePatternItemsHasRest> items (
+ new AST::SlicePatternItemsHasRest (
+ std::move (patterns), std::move (upper_patterns.value ())));
+ return std::unique_ptr<AST::SlicePattern> (
+ new AST::SlicePattern (std::move (items), square_locus));
+ }
+
+ // Rest-less slice pattern
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
/* Parses an identifier pattern (pattern that binds a value matched to a
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index 4890d8e..6b57c6d 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -584,6 +584,14 @@ ResolverBase::visit (AST::GroupedPattern &)
{}
void
+ResolverBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+
+void
+ResolverBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+
+void
ResolverBase::visit (AST::SlicePattern &)
{}
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index dce8e7b..febfc61 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -186,6 +186,8 @@ public:
void visit (AST::TuplePatternItemsRanged &);
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
+ void visit (AST::SlicePatternItemsNoRest &);
+ void visit (AST::SlicePatternItemsHasRest &);
void visit (AST::SlicePattern &);
void visit (AST::AltPattern &);
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index fce45bc..3b80f9f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -388,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern)
void
PatternDeclaration::visit (AST::SlicePattern &pattern)
{
- for (auto &p : pattern.get_items ())
+ auto &items = pattern.get_items ();
+ switch (items.get_pattern_type ())
{
- p->accept_vis (*this);
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
+
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_lower_patterns ())
+ p->accept_vis (*this);
+ for (auto &p : ref.get_upper_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
}
}