Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gcc/rust/ast/rust-ast-collector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ());
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/ast/rust-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
16 changes: 8 additions & 8 deletions gcc/rust/ast/rust-pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -859,29 +859,29 @@ class StructPatternElements
* 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 ());
Expand All @@ -893,7 +893,7 @@ class StructPatternElements
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 ());
Expand Down Expand Up @@ -938,7 +938,7 @@ class StructPatternElements

void strip_etc ()
{
has_struct_pattern_etc = false;
has_rest_pattern = false;
struct_pattern_etc_attrs.clear ();
struct_pattern_etc_attrs.shrink_to_fit ();
}
Expand Down
5 changes: 3 additions & 2 deletions gcc/rust/backend/rust-compile-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -885,8 +885,9 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
rust_assert (ok);
}

rust_assert (variant->get_variant_type ()
== TyTy::VariantDef::VariantType::STRUCT);
rust_assert (
variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT
|| variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE);

auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/expand/rust-cfg-strip.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()))
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/hir/rust-ast-lower-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ())
Expand Down Expand Up @@ -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));
}

Expand Down
18 changes: 14 additions & 4 deletions gcc/rust/hir/tree/rust-hir-pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ class StructPatternFieldIdent : public StructPatternField
class StructPatternElements
{
std::vector<std::unique_ptr<StructPatternField>> fields;
bool has_rest_pattern;

public:
// Returns whether there are any struct pattern fields
Expand All @@ -692,18 +693,27 @@ class StructPatternElements
* 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
StructPatternElements (StructPatternElements const &other)
{
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
Expand All @@ -712,8 +722,8 @@ class StructPatternElements
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;
}

Expand Down
21 changes: 20 additions & 1 deletion gcc/rust/hir/tree/rust-hir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2519,10 +2519,29 @@ StructPatternField::as_string () const
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
str += "\n " + attr.as_string ();
}
}

str += "\n item type: ";
switch (get_item_type ())
{
case ItemType::TUPLE_PAT:
str += "TUPLE_PAT";
break;
case ItemType::IDENT_PAT:
str += "IDENT_PAT";
break;
case ItemType::IDENT:
str += "IDENT";
break;
default:
str += "UNKNOWN";
break;
}

str += "\n mapping: " + mappings.as_string ();

return str;
}

Expand Down
6 changes: 3 additions & 3 deletions gcc/rust/parse/rust-parse-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand All @@ -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;
}

Expand All @@ -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
Expand Down
40 changes: 33 additions & 7 deletions gcc/rust/typecheck/rust-hir-type-check-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)

// error[E0532]: expected tuple struct or tuple variant, found struct
// variant `Foo::D`
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
bool error_E0532 = false;
if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
{
// Tuple structs can still be matched with struct patterns via index
// numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
// type TUPLE_PAT. Throw E0532 if not.
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
{
if (field->get_item_type ()
!= HIR::StructPatternField::ItemType::TUPLE_PAT)
{
error_E0532 = true;
break;
}
}
}
else if (variant->get_variant_type ()
!= TyTy::VariantDef::VariantType::STRUCT)
{
error_E0532 = true;
}

if (error_E0532)
{
std::string variant_type
= TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
Expand Down Expand Up @@ -407,7 +430,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;

Expand Down Expand Up @@ -507,7 +531,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
{
emit_pattern_size_error (pattern, par.get_fields ().size (),
min_size_required);
// TODO attempt to continue to do typechecking even after wrong size
// TODO attempt to continue to do typechecking even after wrong
// size
break;
}

Expand Down Expand Up @@ -679,10 +704,11 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)

if (cap_wi < pattern_min_cap)
{
rust_error_at (
pattern.get_locus (), ErrorCode::E0528,
"pattern requires at least %lu elements but array has %lu",
(unsigned long) pattern_min_cap, (unsigned long) cap_wi);
rust_error_at (pattern.get_locus (), ErrorCode::E0528,
"pattern requires at least %lu elements but "
"array has %lu",
(unsigned long) pattern_min_cap,
(unsigned long) cap_wi);
break;
}
}
Expand Down
9 changes: 9 additions & 0 deletions gcc/testsuite/rust/compile/issue-3929-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// { dg-options "-w" }
struct S();

fn main() {
let s = S{};
match s {
S{..} => {}
}
}
12 changes: 12 additions & 0 deletions gcc/testsuite/rust/compile/issue-3929-2.rs
Original file line number Diff line number Diff line change
@@ -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, ..} => {}
}
}
Loading