Skip to content

Commit 8836ed1

Browse files
Polygonalrphilberty
authored andcommitted
Add HIR lowering support for rest pattern in struct patterns' AST
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]>
1 parent 18ad440 commit 8836ed1

File tree

10 files changed

+54
-22
lines changed

10 files changed

+54
-22
lines changed

gcc/rust/ast/rust-ast-collector.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2620,7 +2620,7 @@ TokenCollector::visit (StructPattern &pattern)
26202620
if (elems.has_struct_pattern_fields ())
26212621
{
26222622
visit_items_joined_by_separator (elems.get_struct_pattern_fields ());
2623-
if (elems.has_etc ())
2623+
if (elems.has_rest ())
26242624
{
26252625
push (Rust::Token::make (COMMA, UNDEF_LOCATION));
26262626
visit_items_as_lines (elems.get_etc_outer_attrs ());

gcc/rust/ast/rust-pattern.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ StructPatternElements::as_string () const
186186
str += "\n " + field->as_string ();
187187
}
188188

189-
str += "\n Etc: ";
190-
if (has_struct_pattern_etc)
189+
str += "\n Has rest: ";
190+
if (has_rest_pattern)
191191
str += "true";
192192
else
193193
str += "false";

gcc/rust/ast/rust-pattern.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ class StructPatternElements
843843
// bool has_struct_pattern_fields;
844844
std::vector<std::unique_ptr<StructPatternField>> fields;
845845

846-
bool has_struct_pattern_etc;
846+
bool has_rest_pattern;
847847
std::vector<Attribute> struct_pattern_etc_attrs;
848848
// StructPatternEtc etc;
849849

@@ -859,29 +859,29 @@ class StructPatternElements
859859
* no etc). */
860860
bool is_empty () const
861861
{
862-
return !has_struct_pattern_fields () && !has_struct_pattern_etc;
862+
return !has_struct_pattern_fields () && !has_rest_pattern;
863863
}
864864

865-
bool has_etc () const { return has_struct_pattern_etc; }
865+
bool has_rest () const { return has_rest_pattern; }
866866

867867
// Constructor for StructPatternElements with both (potentially)
868868
StructPatternElements (
869869
std::vector<std::unique_ptr<StructPatternField>> fields,
870870
std::vector<Attribute> etc_attrs)
871-
: fields (std::move (fields)), has_struct_pattern_etc (true),
871+
: fields (std::move (fields)), has_rest_pattern (true),
872872
struct_pattern_etc_attrs (std::move (etc_attrs))
873873
{}
874874

875875
// Constructor for StructPatternElements with no StructPatternEtc
876876
StructPatternElements (
877877
std::vector<std::unique_ptr<StructPatternField>> fields)
878-
: fields (std::move (fields)), has_struct_pattern_etc (false),
878+
: fields (std::move (fields)), has_rest_pattern (false),
879879
struct_pattern_etc_attrs ()
880880
{}
881881

882882
// Copy constructor with vector clone
883883
StructPatternElements (StructPatternElements const &other)
884-
: has_struct_pattern_etc (other.has_struct_pattern_etc),
884+
: has_rest_pattern (other.has_rest_pattern),
885885
struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
886886
{
887887
fields.reserve (other.fields.size ());
@@ -893,7 +893,7 @@ class StructPatternElements
893893
StructPatternElements &operator= (StructPatternElements const &other)
894894
{
895895
struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
896-
has_struct_pattern_etc = other.has_struct_pattern_etc;
896+
has_rest_pattern = other.has_rest_pattern;
897897

898898
fields.clear ();
899899
fields.reserve (other.fields.size ());
@@ -938,7 +938,7 @@ class StructPatternElements
938938

939939
void strip_etc ()
940940
{
941-
has_struct_pattern_etc = false;
941+
has_rest_pattern = false;
942942
struct_pattern_etc_attrs.clear ();
943943
struct_pattern_etc_attrs.shrink_to_fit ();
944944
}

gcc/rust/expand/rust-cfg-strip.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2349,7 +2349,7 @@ CfgStrip::visit (AST::StructPattern &pattern)
23492349
maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ());
23502350

23512351
// assuming you can strip the ".." part
2352-
if (elems.has_etc ())
2352+
if (elems.has_rest ())
23532353
{
23542354
expand_cfg_attrs (elems.get_etc_outer_attrs ());
23552355
if (fails_cfg_with_expand (elems.get_etc_outer_attrs ()))

gcc/rust/hir/rust-ast-lower-pattern.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
121121
= ASTLowerPathInExpression::translate (pattern.get_path ());
122122

123123
auto &raw_elems = pattern.get_struct_pattern_elems ();
124-
rust_assert (!raw_elems.has_etc ());
125124

126125
std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
127126
for (auto &field : raw_elems.get_struct_pattern_fields ())
@@ -204,7 +203,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
204203
mappings.get_next_hir_id (crate_num),
205204
UNKNOWN_LOCAL_DEFID);
206205

207-
HIR::StructPatternElements elems (std::move (fields));
206+
HIR::StructPatternElements elems (
207+
std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
208208
translated = new HIR::StructPattern (mapping, *path, std::move (elems));
209209
}
210210

gcc/rust/hir/tree/rust-hir-pattern.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ class StructPatternFieldIdent : public StructPatternField
683683
class StructPatternElements
684684
{
685685
std::vector<std::unique_ptr<StructPatternField>> fields;
686+
bool has_rest_pattern;
686687

687688
public:
688689
// Returns whether there are any struct pattern fields
@@ -692,18 +693,27 @@ class StructPatternElements
692693
* no etc). */
693694
bool is_empty () const { return !has_struct_pattern_fields (); }
694695

696+
bool has_rest () const { return has_rest_pattern; }
697+
695698
// Constructor for StructPatternElements with both (potentially)
696699
StructPatternElements (
697700
std::vector<std::unique_ptr<StructPatternField>> fields)
698-
: fields (std::move (fields))
701+
: fields (std::move (fields)), has_rest_pattern (false)
702+
{}
703+
704+
StructPatternElements (
705+
std::vector<std::unique_ptr<StructPatternField>> fields,
706+
bool has_rest_pattern)
707+
: fields (std::move (fields)), has_rest_pattern (has_rest_pattern)
699708
{}
700709

701710
// Copy constructor with vector clone
702711
StructPatternElements (StructPatternElements const &other)
703712
{
704713
fields.reserve (other.fields.size ());
705714
for (const auto &e : other.fields)
706-
fields.push_back (e->clone_struct_pattern_field ());
715+
fields.emplace_back (e->clone_struct_pattern_field ());
716+
has_rest_pattern = other.has_rest_pattern;
707717
}
708718

709719
// Overloaded assignment operator with vector clone
@@ -712,8 +722,8 @@ class StructPatternElements
712722
fields.clear ();
713723
fields.reserve (other.fields.size ());
714724
for (const auto &e : other.fields)
715-
fields.push_back (e->clone_struct_pattern_field ());
716-
725+
fields.emplace_back (e->clone_struct_pattern_field ());
726+
has_rest_pattern = other.has_rest_pattern;
717727
return *this;
718728
}
719729

gcc/rust/parse/rust-parse-impl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11430,7 +11430,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
1143011430
std::vector<std::unique_ptr<AST::StructPatternField>> fields;
1143111431

1143211432
AST::AttrVec etc_attrs;
11433-
bool has_etc = false;
11433+
bool has_rest = false;
1143411434

1143511435
// try parsing struct pattern fields
1143611436
const_TokenPtr t = lexer.peek_token ();
@@ -11443,7 +11443,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
1144311443
{
1144411444
lexer.skip_token ();
1144511445
etc_attrs = std::move (outer_attrs);
11446-
has_etc = true;
11446+
has_rest = true;
1144711447
break;
1144811448
}
1144911449

@@ -11468,7 +11468,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
1146811468
t = lexer.peek_token ();
1146911469
}
1147011470

11471-
if (has_etc)
11471+
if (has_rest)
1147211472
return AST::StructPatternElements (std::move (fields),
1147311473
std::move (etc_attrs));
1147411474
else

gcc/rust/typecheck/rust-hir-type-check-pattern.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
407407
// Expects enum struct or struct struct.
408408
// error[E0027]: pattern does not mention fields `x`, `y`
409409
// error[E0026]: variant `Foo::D` does not have a field named `b`
410-
if (named_fields.size () != variant->num_fields ())
410+
if (!pattern.get_struct_pattern_elems ().has_rest ()
411+
&& named_fields.size () != variant->num_fields ())
411412
{
412413
std::map<std::string, bool> missing_names;
413414

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// { dg-options "-w" }
2+
struct S();
3+
4+
fn main() {
5+
let s = S{};
6+
match s {
7+
S{..} => {}
8+
}
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// { dg-options "-w" }
2+
struct S {
3+
x: i32,
4+
y: i32,
5+
}
6+
7+
fn main() {
8+
let s = S{x: 1, y: 2};
9+
match s {
10+
S{x: 1, ..} => {}
11+
}
12+
}

0 commit comments

Comments
 (0)