aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc82
-rw-r--r--gcc/testsuite/rust/compile/match8.rs19
2 files changed, 76 insertions, 25 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 1a3d0ec..2b0b02a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -222,10 +222,6 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
return;
}
- // check the elements
- // error[E0027]: pattern does not mention fields `x`, `y`
- // error[E0026]: variant `Foo::D` does not have a field named `b`
-
std::vector<std::string> named_fields;
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
@@ -279,31 +275,67 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
}
}
- if (named_fields.size () != variant->num_fields ())
+ // check the elements
+ if (adt->is_union ())
{
- std::map<std::string, bool> missing_names;
+ auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
+ if (struct_pattern_elems.get_struct_pattern_fields ().size () != 1)
+ rust_error_at (pattern.get_locus (),
+ "union patterns should have exactly one field");
- // populate with all fields
- for (auto &field : variant->get_fields ())
- missing_names[field->get_name ()] = true;
-
- // then eliminate with named_fields
- for (auto &named : named_fields)
- missing_names.erase (named);
-
- // then get the list of missing names
- size_t i = 0;
- std::string missing_fields_str;
- for (auto it = missing_names.begin (); it != missing_names.end (); it++)
+ else
+ {
+ switch (struct_pattern_elems.get_struct_pattern_fields ()
+ .at (0)
+ ->get_item_type ())
+ {
+ case HIR::StructPatternField::ItemType::IDENT:
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ break;
+ default: {
+ auto first_elem
+ = struct_pattern_elems.get_struct_pattern_fields ()
+ .at (0)
+ ->as_string ();
+ rust_error_at (pattern.get_locus (),
+ "%qs cannot be used in union patterns",
+ first_elem.c_str ());
+ }
+ }
+ }
+ }
+ else
+ {
+ // 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 ())
{
- bool has_next = (i + 1) < missing_names.size ();
- missing_fields_str += it->first + (has_next ? ", " : "");
- i++;
+ std::map<std::string, bool> missing_names;
+
+ // populate with all fields
+ for (auto &field : variant->get_fields ())
+ missing_names[field->get_name ()] = true;
+
+ // then eliminate with named_fields
+ for (auto &named : named_fields)
+ missing_names.erase (named);
+
+ // then get the list of missing names
+ size_t i = 0;
+ std::string missing_fields_str;
+ for (auto it = missing_names.begin (); it != missing_names.end ();
+ it++)
+ {
+ bool has_next = (i + 1) < missing_names.size ();
+ missing_fields_str += it->first + (has_next ? ", " : "");
+ i++;
+ }
+
+ rust_error_at (pattern.get_locus (), ErrorCode::E0027,
+ "pattern does not mention fields %s",
+ missing_fields_str.c_str ());
}
-
- rust_error_at (pattern.get_locus (), ErrorCode::E0027,
- "pattern does not mention fields %s",
- missing_fields_str.c_str ());
}
}
diff --git a/gcc/testsuite/rust/compile/match8.rs b/gcc/testsuite/rust/compile/match8.rs
new file mode 100644
index 0000000..336b313
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match8.rs
@@ -0,0 +1,19 @@
+union MyUnion {
+ f1: u32,
+ f2: f32,
+}
+
+fn f(u: MyUnion) -> i32 {
+ unsafe {
+ match u {
+ MyUnion { f1: 10 } => 0,
+ MyUnion { f2 } => 0,
+ MyUnion { f1: 10, f2: 10.0 } => 0, // { dg-error "union patterns should have exactly one field" "" }
+ MyUnion {} => 0, // { dg-error "union patterns should have exactly one field" "" }
+ MyUnion { f1: () } => 0, // { dg-error "expected u32, found tuple" "" }
+ _ => 1,
+ }
+ }
+}
+
+fn main() {}