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
59 changes: 49 additions & 10 deletions gcc/rust/backend/rust-compile-var-decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,66 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor

void visit (HIR::TuplePattern &pattern) override
{
rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
switch (pattern.get_items ().get_item_type ())
{
case HIR::TuplePatternItems::ItemType::NO_REST:
{
rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
auto &items = static_cast<HIR::TuplePatternItemsNoRest &> (
auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
pattern.get_items ());

size_t offs = 0;
for (auto &sub : items.get_patterns ())
tree field = TYPE_FIELDS (translated_type);
for (auto &sub : items_no_rest.get_patterns ())
{
tree sub_ty = error_mark_node;
tree field = TYPE_FIELDS (translated_type);
for (size_t i = 0; i < offs; i++)
gcc_assert (field != NULL_TREE);
tree sub_ty = TREE_TYPE (field);
CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
field = DECL_CHAIN (field);
}
}
break;

case HIR::TuplePatternItems::ItemType::HAS_REST:
{
auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
pattern.get_items ());

// count total fields in translated_type
size_t total_fields = 0;
for (tree t = TYPE_FIELDS (translated_type); t; t = DECL_CHAIN (t))
{
total_fields++;
}

// process lower patterns
tree field = TYPE_FIELDS (translated_type);
for (auto &sub : items_has_rest.get_lower_patterns ())
{
gcc_assert (field != NULL_TREE);
tree sub_ty = TREE_TYPE (field);
CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
field = DECL_CHAIN (field);
}

// process upper patterns
if (!items_has_rest.get_upper_patterns ().empty ())
{
size_t upper_start
= total_fields - items_has_rest.get_upper_patterns ().size ();
field = TYPE_FIELDS (translated_type);
for (size_t i = 0; i < upper_start; i++)
{
field = DECL_CHAIN (field);
gcc_assert (field != NULL_TREE);
}
sub_ty = TREE_TYPE (field);
CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
offs++;

for (auto &sub : items_has_rest.get_upper_patterns ())
{
gcc_assert (field != NULL_TREE);
tree sub_ty = TREE_TYPE (field);
CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
field = DECL_CHAIN (field);
}
}
}
break;
Expand Down
14 changes: 12 additions & 2 deletions gcc/rust/checks/errors/rust-readonly-check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,24 @@ ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
{
case HIR::TuplePatternItems::ItemType::NO_REST:
{
auto &items = static_cast<HIR::TuplePatternItemsNoRest &> (
auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
tuple_pattern.get_items ());
for (auto &sub : items.get_patterns ())
for (auto &sub : items_no_rest.get_patterns ())
{
collect_assignment (*sub, has_init_expr);
}
}
break;
case HIR::TuplePatternItems::ItemType::HAS_REST:
{
auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
tuple_pattern.get_items ());
for (auto &sub : items_has_rest.get_lower_patterns ())
collect_assignment (*sub, has_init_expr);
for (auto &sub : items_has_rest.get_upper_patterns ())
collect_assignment (*sub, has_init_expr);
}
break;
default:
break;
}
Expand Down
4 changes: 4 additions & 0 deletions gcc/testsuite/rust/compile/issue-3930.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// { dg-additional-options "-w" }
fn main() {
let (a, .., b) = (2, 3);
}
5 changes: 5 additions & 0 deletions gcc/testsuite/rust/compile/tuplepattern-rest-readonly.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
let (a, .., b) = (1, 1);
a = 2; // { dg-error "assignment of read-only variable .a." }
b = 2; // { dg-error "assignment of read-only variable .b." }
}
Loading