From: Yap Zhi Heng <[email protected]>
gcc/rust/ChangeLog:
* ast/rust-pattern.h (StructPatternElements): Rename
has_struct_pattern_etc
to has_rest_pattern, and has_etc to has_rest to signify presense of rest
patterns more clearly.
* ast/rust-pattern.cc (StructPatternElements::as_string): Rename
variables
accordingly.
* ast/rust-ast-collector.cc: Rename variables accordingly.
* expand/rust-cfg-strip.cc: Rename variables accordingly.
* parse/rust-parse-impl.h: Rename variable accordingly.
* hir/tree/rust-hir-pattern.h (StructPatternElements): Add a boolean to
track
presense of rest pattern.
* hir/rust-ast-lower-pattern.cc (visit(StructPattern)): Add support for
lowering rest pattern to HIR.
* typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)):
Remove
size check when rest pattern is present.
Signed-off-by: Yap Zhi Heng <[email protected]>
---
gcc/rust/ast/rust-ast-collector.cc | 2 +-
gcc/rust/ast/rust-pattern.cc | 4 ++--
gcc/rust/ast/rust-pattern.h | 16 ++++++++--------
gcc/rust/expand/rust-cfg-strip.cc | 2 +-
gcc/rust/hir/rust-ast-lower-pattern.cc | 4 ++--
gcc/rust/hir/tree/rust-hir-pattern.h | 18 ++++++++++++++----
gcc/rust/parse/rust-parse-impl.h | 6 +++---
.../typecheck/rust-hir-type-check-pattern.cc | 3 ++-
gcc/testsuite/rust/compile/issue-3929-1.rs | 9 +++++++++
gcc/testsuite/rust/compile/issue-3929-2.rs | 12 ++++++++++++
10 files changed, 54 insertions(+), 22 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-3929-1.rs
create mode 100644 gcc/testsuite/rust/compile/issue-3929-2.rs
diff --git a/gcc/rust/ast/rust-ast-collector.cc
b/gcc/rust/ast/rust-ast-collector.cc
index 842f35f288d..721d274a838 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -2620,7 +2620,7 @@ TokenCollector::visit (StructPattern &pattern)
if (elems.has_struct_pattern_fields ())
{
visit_items_joined_by_separator (elems.get_struct_pattern_fields ());
- if (elems.has_etc ())
+ if (elems.has_rest ())
{
push (Rust::Token::make (COMMA, UNDEF_LOCATION));
visit_items_as_lines (elems.get_etc_outer_attrs ());
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index ebe872402ea..a2fe5d59081 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -186,8 +186,8 @@ StructPatternElements::as_string () const
str += "\n " + field->as_string ();
}
- str += "\n Etc: ";
- if (has_struct_pattern_etc)
+ str += "\n Has rest: ";
+ if (has_rest_pattern)
str += "true";
else
str += "false";
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 51986763fad..0da1981928f 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -843,7 +843,7 @@ class StructPatternElements
// bool has_struct_pattern_fields;
std::vector<std::unique_ptr<StructPatternField>> fields;
- bool has_struct_pattern_etc;
+ bool has_rest_pattern;
std::vector<Attribute> struct_pattern_etc_attrs;
// StructPatternEtc etc;
@@ -859,29 +859,29 @@ public:
* no etc). */
bool is_empty () const
{
- return !has_struct_pattern_fields () && !has_struct_pattern_etc;
+ return !has_struct_pattern_fields () && !has_rest_pattern;
}
- bool has_etc () const { return has_struct_pattern_etc; }
+ bool has_rest () const { return has_rest_pattern; }
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields,
std::vector<Attribute> etc_attrs)
- : fields (std::move (fields)), has_struct_pattern_etc (true),
+ : fields (std::move (fields)), has_rest_pattern (true),
struct_pattern_etc_attrs (std::move (etc_attrs))
{}
// Constructor for StructPatternElements with no StructPatternEtc
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields)
- : fields (std::move (fields)), has_struct_pattern_etc (false),
+ : fields (std::move (fields)), has_rest_pattern (false),
struct_pattern_etc_attrs ()
{}
// Copy constructor with vector clone
StructPatternElements (StructPatternElements const &other)
- : has_struct_pattern_etc (other.has_struct_pattern_etc),
+ : has_rest_pattern (other.has_rest_pattern),
struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
{
fields.reserve (other.fields.size ());
@@ -893,7 +893,7 @@ public:
StructPatternElements &operator= (StructPatternElements const &other)
{
struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
- has_struct_pattern_etc = other.has_struct_pattern_etc;
+ has_rest_pattern = other.has_rest_pattern;
fields.clear ();
fields.reserve (other.fields.size ());
@@ -938,7 +938,7 @@ public:
void strip_etc ()
{
- has_struct_pattern_etc = false;
+ has_rest_pattern = false;
struct_pattern_etc_attrs.clear ();
struct_pattern_etc_attrs.shrink_to_fit ();
}
diff --git a/gcc/rust/expand/rust-cfg-strip.cc
b/gcc/rust/expand/rust-cfg-strip.cc
index 3bc8461c4ff..3c5e74e7aae 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -2349,7 +2349,7 @@ CfgStrip::visit (AST::StructPattern &pattern)
maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ());
// assuming you can strip the ".." part
- if (elems.has_etc ())
+ if (elems.has_rest ())
{
expand_cfg_attrs (elems.get_etc_outer_attrs ());
if (fails_cfg_with_expand (elems.get_etc_outer_attrs ()))
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc
b/gcc/rust/hir/rust-ast-lower-pattern.cc
index a209f80f4da..00d1bc8c33e 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -121,7 +121,6 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
= ASTLowerPathInExpression::translate (pattern.get_path ());
auto &raw_elems = pattern.get_struct_pattern_elems ();
- rust_assert (!raw_elems.has_etc ());
std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
for (auto &field : raw_elems.get_struct_pattern_fields ())
@@ -204,7 +203,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- HIR::StructPatternElements elems (std::move (fields));
+ HIR::StructPatternElements elems (
+ std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
translated = new HIR::StructPattern (mapping, *path, std::move (elems));
}
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h
b/gcc/rust/hir/tree/rust-hir-pattern.h
index e954aec309f..89b9cc6a06c 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -683,6 +683,7 @@ protected:
class StructPatternElements
{
std::vector<std::unique_ptr<StructPatternField>> fields;
+ bool has_rest_pattern;
public:
// Returns whether there are any struct pattern fields
@@ -692,10 +693,18 @@ public:
* no etc). */
bool is_empty () const { return !has_struct_pattern_fields (); }
+ bool has_rest () const { return has_rest_pattern; }
+
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields)
- : fields (std::move (fields))
+ : fields (std::move (fields)), has_rest_pattern (false)
+ {}
+
+ StructPatternElements (
+ std::vector<std::unique_ptr<StructPatternField>> fields,
+ bool has_rest_pattern)
+ : fields (std::move (fields)), has_rest_pattern (has_rest_pattern)
{}
// Copy constructor with vector clone
@@ -703,7 +712,8 @@ public:
{
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
- fields.push_back (e->clone_struct_pattern_field ());
+ fields.emplace_back (e->clone_struct_pattern_field ());
+ has_rest_pattern = other.has_rest_pattern;
}
// Overloaded assignment operator with vector clone
@@ -712,8 +722,8 @@ public:
fields.clear ();
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
- fields.push_back (e->clone_struct_pattern_field ());
-
+ fields.emplace_back (e->clone_struct_pattern_field ());
+ has_rest_pattern = other.has_rest_pattern;
return *this;
}
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index c54685d44ba..ec4c1c1d6c7 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -11430,7 +11430,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems
()
std::vector<std::unique_ptr<AST::StructPatternField>> fields;
AST::AttrVec etc_attrs;
- bool has_etc = false;
+ bool has_rest = false;
// try parsing struct pattern fields
const_TokenPtr t = lexer.peek_token ();
@@ -11443,7 +11443,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems
()
{
lexer.skip_token ();
etc_attrs = std::move (outer_attrs);
- has_etc = true;
+ has_rest = true;
break;
}
@@ -11468,7 +11468,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems
()
t = lexer.peek_token ();
}
- if (has_etc)
+ if (has_rest)
return AST::StructPatternElements (std::move (fields),
std::move (etc_attrs));
else
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 5a2dde85e18..7b405510bb3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -407,7 +407,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
// Expects enum struct or struct struct.
// error[E0027]: pattern does not mention fields `x`, `y`
// error[E0026]: variant `Foo::D` does not have a field named `b`
- if (named_fields.size () != variant->num_fields ())
+ if (!pattern.get_struct_pattern_elems ().has_rest ()
+ && named_fields.size () != variant->num_fields ())
{
std::map<std::string, bool> missing_names;
diff --git a/gcc/testsuite/rust/compile/issue-3929-1.rs
b/gcc/testsuite/rust/compile/issue-3929-1.rs
new file mode 100644
index 00000000000..3d7b0568b55
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3929-1.rs
@@ -0,0 +1,9 @@
+// { dg-options "-w" }
+struct S();
+
+fn main() {
+ let s = S{};
+ match s {
+ S{..} => {}
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3929-2.rs
b/gcc/testsuite/rust/compile/issue-3929-2.rs
new file mode 100644
index 00000000000..5f45a7c050a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3929-2.rs
@@ -0,0 +1,12 @@
+// { dg-options "-w" }
+struct S {
+ x: i32,
+ y: i32,
+}
+
+fn main() {
+ let s = S{x: 1, y: 2};
+ match s {
+ S{x: 1, ..} => {}
+ }
+}
--
2.50.1