From: Owen Avery <[email protected]>
Slice patterns with bound rest patterns still aren't supported in type
checking and compilation to GENERIC.
gcc/rust/ChangeLog:
* backend/rust-compile-pattern.cc
(CompilePatternBindings::visit (SlicePattern)): Assert that the
rest pattern isn't bound (currently unsupported).
* checks/errors/borrowck/rust-bir-builder-pattern.cc
(PatternBindingBuilder::visit (SlicePattern)): Handle bound rest
pattern.
* checks/errors/rust-ast-validation.cc
(ASTValidation::visit (AST::SlicePattern)): Likewise.
* hir/rust-ast-lower-pattern.cc
(ASTLoweringPattern::visit (AST::SlicePattern)): Likewise.
* hir/rust-hir-dump.cc (Dump::visit (SlicePatternItemsHasRest)):
Likewise.
* hir/tree/rust-hir-pattern.h
(SlicePatternItemsHasRest::rest_bind): New member variable.
(SlicePatternItemsHasRest::SlicePatternItemsHasRest): Initialize
rest_bind.
(SlicePatternItemsHasRest::operator=): Likewise.
(SlicePatternItemsHasRest::has_rest_bind): New member function.
(SlicePatternItemsHasRest::get_rest_bind): Likewise.
* hir/tree/rust-hir-visitor.cc
(DefaultHIRVisitor::walk (SlicePatternItemsHasRest)): Handle
bound rest pattern.
* hir/tree/rust-hir.cc (SlicePatternItemsHasRest::to_string):
Likewise.
* typecheck/rust-hir-type-check-pattern.cc
(TypeCheckPattern::visit (SlicePattern)): Assert that the rest
pattern isn't bound (currently unsupported).
gcc/testsuite/ChangeLog:
* rust/compile/slice_rest_pattern_2.rs: New test.
Signed-off-by: Owen Avery <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github: https://github.com/Rust-GCC/gccrs/commit/78016dea955c55b476aef6a2d54786b060246c51
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4774
gcc/rust/backend/rust-compile-pattern.cc | 4 ++
.../borrowck/rust-bir-builder-pattern.cc | 4 ++
gcc/rust/checks/errors/rust-ast-validation.cc | 21 +++++++++--
gcc/rust/hir/rust-ast-lower-pattern.cc | 37 +++++++++++++++++--
gcc/rust/hir/rust-hir-dump.cc | 2 +
gcc/rust/hir/tree/rust-hir-pattern.h | 26 ++++++++++++-
gcc/rust/hir/tree/rust-hir-visitor.cc | 2 +
gcc/rust/hir/tree/rust-hir.cc | 6 +++
.../typecheck/rust-hir-type-check-pattern.cc | 4 ++
.../rust/compile/slice_rest_pattern_2.rs | 11 ++++++
10 files changed, 107 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/slice_rest_pattern_2.rs
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index e2f54d7ac..19f5bc4ed 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -1233,6 +1233,10 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern)
{
auto &items
= static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ // TODO: support rest_bind (c in [a, b, c @ ..])
+ rust_assert (!items.has_rest_bind ());
+
for (auto &pattern_member : items.get_lower_patterns ())
{
tree index_tree
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
index e78d75050..5bd061470 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -92,6 +92,10 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern)
{
member->accept_vis (*this);
}
+ if (items.has_rest_bind ())
+ {
+ items.get_rest_bind ().accept_vis (*this);
+ }
for (auto &member : items.get_upper_patterns ())
{
member->accept_vis (*this);
diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index e3262b947..b2825fb2c 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -205,14 +205,27 @@ ASTValidation::visit (AST::SlicePattern &pattern)
// for nicer errors
bool had_rest = false;
+ auto note_rest = [&] (location_t locus) {
+ if (had_rest)
+ rust_error_at (locus, "%<..%> can only be used once per slice pattern");
+ had_rest = true;
+ };
+
for (auto &pat : pattern.get_patterns ())
{
if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
{
- if (had_rest)
- rust_error_at (pat->get_locus (),
- "%<..%> can only be used once per slice pattern");
- had_rest = true;
+ note_rest (pat->get_locus ());
+ }
+ else if (pat->get_pattern_kind () == AST::Pattern::Kind::Identifier)
+ {
+ auto &ident_pat = static_cast<AST::IdentifierPattern &> (*pat);
+ if (ident_pat.has_subpattern ())
+ {
+ auto &ident_sub_pat = ident_pat.get_subpattern ();
+ if (ident_sub_pat.get_pattern_kind () == AST::Pattern::Kind::Rest)
+ note_rest (ident_sub_pat.get_locus ());
+ }
}
}
}
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index b19a6411d..17d4dc981 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -353,17 +353,46 @@ void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
tl::optional<size_t> rest_index;
+ tl::optional<HIR::IdentifierPattern> rest_bind;
std::vector<std::unique_ptr<AST::Pattern>> &sub_patterns
= pattern.get_patterns ();
+ // need this earlier than usual
+ // since we might need to produce rest_bind
+ auto crate_num = mappings.get_current_crate ();
+
for (size_t i = 0; i < sub_patterns.size (); i++)
{
auto &pat = sub_patterns[i];
- if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
+
+ // ASTValidation verified there's only one Rest pattern
+ // so we can break once we find the first one
+ if (pat->get_pattern_kind () == AST::Pattern::Kind::Identifier)
+ {
+ auto &ident_pat = static_cast<AST::IdentifierPattern &> (*pat);
+ if (ident_pat.has_subpattern ())
+ {
+ if (ident_pat.get_subpattern ().get_pattern_kind ()
+ == AST::Pattern::Kind::Rest)
+ {
+ Analysis::NodeMapping rest_bind_mapping (
+ crate_num, ident_pat.get_node_id (),
+ mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+
+ rest_bind = HIR::IdentifierPattern (
+ std::move (rest_bind_mapping), ident_pat.get_ident (),
+ ident_pat.get_locus (), ident_pat.get_is_ref (),
+ ident_pat.get_is_mut () ? Mutability::Mut
+ : Mutability::Imm);
+ rest_index = i;
+ break;
+ }
+ }
+ }
+ else if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
{
rest_index = i;
- // ASTValidation verified there's only one Rest pattern
break;
}
}
@@ -375,7 +404,8 @@ ASTLoweringPattern::visit (AST::SlicePattern &pattern)
auto rest_it = sub_patterns.begin () + *rest_index;
items = std::make_unique<HIR::SlicePatternItemsHasRest> (
lower_pattern_seq (sub_patterns.begin (), rest_it),
- lower_pattern_seq (rest_it + 1, sub_patterns.end ()));
+ lower_pattern_seq (rest_it + 1, sub_patterns.end ()),
+ std::move (rest_bind));
}
else
{
@@ -383,7 +413,6 @@ ASTLoweringPattern::visit (AST::SlicePattern &pattern)
lower_pattern_seq (sub_patterns.begin (), sub_patterns.end ()));
}
- auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 29b3ff92a..f21522b4d 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -2375,6 +2375,8 @@ Dump::visit (SlicePatternItemsHasRest &e)
{
begin ("SlicePatternItemsHasRest");
visit_collection ("lower_patterns", e.get_lower_patterns ());
+ if (e.has_rest_bind ())
+ visit_field ("rest_bind", e.get_rest_bind ());
visit_collection ("upper_patterns", e.get_upper_patterns ());
end ("SlicePatternItemsHasRest");
}
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 90f8f5792..a56379d4a 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1437,16 +1437,22 @@ class SlicePatternItemsHasRest : public SlicePatternItems
std::vector<std::unique_ptr<Pattern>> lower_patterns;
std::vector<std::unique_ptr<Pattern>> upper_patterns;
+ // c in [a, b, c @ ..]
+ tl::optional<IdentifierPattern> rest_bind;
+
public:
SlicePatternItemsHasRest (
std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ std::vector<std::unique_ptr<Pattern>> upper_patterns,
+ tl::optional<IdentifierPattern> rest_bind)
: lower_patterns (std::move (lower_patterns)),
- upper_patterns (std::move (upper_patterns))
+ upper_patterns (std::move (upper_patterns)),
+ rest_bind (std::move (rest_bind))
{}
// Copy constructor with vector clone
SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
+ : rest_bind (other.rest_bind)
{
lower_patterns.reserve (other.lower_patterns.size ());
for (const auto &e : other.lower_patterns)
@@ -1470,6 +1476,8 @@ public:
for (const auto &e : other.upper_patterns)
upper_patterns.push_back (e->clone_pattern ());
+ rest_bind = other.rest_bind;
+
return *this;
}
@@ -1502,6 +1510,20 @@ public:
return upper_patterns;
}
+ bool has_rest_bind () const { return rest_bind.has_value (); }
+
+ IdentifierPattern &get_rest_bind ()
+ {
+ rust_assert (has_rest_bind ());
+ return *rest_bind;
+ }
+
+ const IdentifierPattern &get_rest_bind () const
+ {
+ rust_assert (has_rest_bind ());
+ return *rest_bind;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc
index 00b46e742..544c83db8 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.cc
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -1077,6 +1077,8 @@ DefaultHIRVisitor::walk (SlicePatternItemsHasRest &items)
{
for (auto &lower : items.get_lower_patterns ())
lower->accept_vis (*this);
+ if (items.has_rest_bind ())
+ items.get_rest_bind ().accept_vis (*this);
for (auto &upper : items.get_upper_patterns ())
upper->accept_vis (*this);
}
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 51b588a02..7d611ed5c 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2449,6 +2449,12 @@ SlicePatternItemsHasRest::to_string () const
}
}
+ str += "\n Rest binding pattern: ";
+ if (rest_bind)
+ str += rest_bind->to_string ();
+ else
+ str += "none";
+
str += "\n Upper patterns: ";
if (upper_patterns.empty ())
{
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 7d12bc7b4..83104833d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -942,6 +942,10 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
{
auto &ref
= static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ // TODO: support rest_bind (c in [a, b, c @ ..])
+ rust_assert (!ref.has_rest_bind ());
+
for (const auto &pattern_member : ref.get_lower_patterns ())
{
TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
diff --git a/gcc/testsuite/rust/compile/slice_rest_pattern_2.rs b/gcc/testsuite/rust/compile/slice_rest_pattern_2.rs
new file mode 100644
index 000000000..10316f750
--- /dev/null
+++ b/gcc/testsuite/rust/compile/slice_rest_pattern_2.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-frust-compile-until=typecheck" }
+#![feature(no_core)]
+#![no_core]
+
+pub fn foo(x: &[u8]) -> i32 {
+ match x {
+ [] => 0,
+ [1, xs @ ..] => foo (xs),
+ [x, ..] => *x as i32
+ }
+}
base-commit: 84167f9bff1edb231d611e9b851f27bd4fe79b9e
--
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.