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
46 changes: 44 additions & 2 deletions gcc/rust/backend/rust-compile-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,50 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
{
case HIR::TuplePatternItems::RANGED:
{
// TODO
gcc_unreachable ();
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
size_t tuple_field_index = 0;

// lookup the type to find out number of fields
TyTy::BaseType *ty = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (
pattern.get_mappings ().get_hirid (), &ty);
rust_assert (ok);
rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);

// compile check expr for lower patterns
for (auto &pat : items.get_lower_patterns ())
{
tree field_expr
= Backend::struct_field_expression (match_scrutinee_expr,
tuple_field_index++,
pat->get_locus ());

tree check_expr_sub
= CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
check_expr = Backend::arithmetic_or_logical_expression (
Comment thread
Polygonalr marked this conversation as resolved.
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
check_expr_sub, pat->get_locus ());
}

// skip the fields that are not checked
tuple_field_index = static_cast<TyTy::TupleType &> (*ty).num_fields ()
- items.get_upper_patterns ().size ();

// compile check expr for upper patterns
for (auto &pat : items.get_upper_patterns ())
{
tree field_expr
= Backend::struct_field_expression (match_scrutinee_expr,
tuple_field_index++,
pat->get_locus ());

tree check_expr_sub
= CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
check_expr = Backend::arithmetic_or_logical_expression (
ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
check_expr_sub, pat->get_locus ());
}
}
break;

Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/typecheck/rust-hir-type-check-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,12 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
HIR::TuplePatternItemsRanged &ref
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());

// Check whether size of lower and upper patterns <= parent size
const auto &lower = ref.get_lower_patterns ();
const auto &upper = ref.get_upper_patterns ();
size_t min_size_required = lower.size () + upper.size ();

if (par.get_fields ().size () > min_size_required)
// Ensure that size of lower and upper patterns <= parent size
if (min_size_required > par.get_fields ().size ())
{
emit_pattern_size_error (pattern, par.get_fields ().size (),
min_size_required);
Expand Down
8 changes: 8 additions & 0 deletions gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let x = (1, 2, 3, 4);

match x {
(1, .., 4) => {},
_ => {}
}
}
8 changes: 8 additions & 0 deletions gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let x = (1, 2, 3, 4);

match x {
(1, .., 2, 3, 4, 5) => {}, // { dg-error "expected a tuple with 4 elements, found one with 5 elements" }
_ => {}
}
}
1 change: 1 addition & 0 deletions gcc/testsuite/rust/compile/tuple_mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ fn main() {
let (_,) = (1, 2); // { dg-error "expected a tuple with 2 elements, found one with 1 element" }
let (_, _) = (1, 2, 3); // { dg-error "expected a tuple with 3 elements, found one with 2 elements" }
let (_, _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" }
let (_, .., _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" }
}

// The lhs and rhs sizes don't match, but we still resolve 'a' to be bool, we don't
Expand Down
27 changes: 27 additions & 0 deletions gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// { dg-output "correct\r*" }
extern "C" {
fn puts(s: *const i8);
}

fn main() -> i32 {
Comment thread
Polygonalr marked this conversation as resolved.
let x = (1, 2, 3, 4);
let mut ret = 1;

match x {
(1, .., 2, 4) => {
/* should not take this path */
unsafe { puts("wrong\0" as *const str as *const i8) }
},
(2, ..) => {
/* should not take this path */
unsafe { puts("wrong\0" as *const str as *const i8) }
},
(b, .., 4) => {
ret -= b;
unsafe { puts("correct\0" as *const str as *const i8) }
},
_ => {}
}

ret
}
Loading