From: Yap Zhi Heng <[email protected]>
gcc/rust/ChangeLog:
* hir/rust-ast-lower-pattern.cc
(ASTLoweringPattern::visit(TupleStructPattern)):
Implement lowering of AST::TupleStructItemsHasRest to HIR.
* typecheck/rust-hir-type-check-pattern.cc
(TypeCheckPattern::visit(TupleStructPattern)):
Add the respective type checking for AST::TupleStructItemsHasRest
* checks/errors/rust-hir-pattern-analysis.cc (lower_tuple_pattern):
Add respective pattern for HAS_REST case.
Signed-off-by: Yap Zhi Heng <[email protected]>
---
.../errors/rust-hir-pattern-analysis.cc | 39 +++++++++++---
gcc/rust/hir/rust-ast-lower-pattern.cc | 29 ++++++++--
.../typecheck/rust-hir-type-check-pattern.cc | 54 ++++++++++++++++---
3 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 13c54e34cce..f132e04ef7b 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -1212,16 +1212,16 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
{
case HIR::TupleStructItems::ItemType::NO_REST:
{
- HIR::TupleStructItemsNoRest &multiple
+ HIR::TupleStructItemsNoRest &items_no_rest
= static_cast<HIR::TupleStructItemsNoRest &> (elems);
rust_assert (variant->get_fields ().size ()
- == multiple.get_patterns ().size ());
+ == items_no_rest.get_patterns ().size ());
- for (size_t i = 0; i < multiple.get_patterns ().size (); i++)
+ for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
{
fields.push_back (
- lower_pattern (ctx, *multiple.get_patterns ().at (i),
+ lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
variant->get_fields ().at (i)->get_field_type ()));
}
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
@@ -1229,8 +1229,35 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
break;
case HIR::TupleStructItems::ItemType::HAS_REST:
{
- // TODO: ranged tuple struct items
- rust_unreachable ();
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (elems);
+
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ rust_assert (num_patterns <= variant->num_fields ());
+
+ size_t i = 0;
+ for (auto &pattern_member : items_has_rest.get_lower_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ while (i < variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ())
+ {
+ fields.push_back (
+ DeconstructedPat::make_wildcard (pattern.get_locus ()));
+ i++;
+ }
+ for (auto &pattern_member : items_has_rest.get_upper_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
default:
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc
b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 00d1bc8c33e..4250adbfbab 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -83,20 +83,39 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
{
case AST::TupleStructItems::HAS_REST:
{
- // TODO
- rust_unreachable ();
+ AST::TupleStructItemsHasRest &items_has_rest
+ = static_cast<AST::TupleStructItemsHasRest &> (items);
+
+ std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+ lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ());
+ for (auto &pattern_member : items_has_rest.get_lower_patterns ())
+ {
+ lower_patterns.emplace_back (
+ ASTLoweringPattern::translate (*pattern_member));
+ }
+
+ std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
+ upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ());
+ for (auto &pattern_member : items_has_rest.get_upper_patterns ())
+ {
+ upper_patterns.emplace_back (
+ ASTLoweringPattern::translate (*pattern_member));
+ }
+
+ lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns));
}
break;
case AST::TupleStructItems::NO_REST:
{
- AST::TupleStructItemsNoRest &items_no_range
+ AST::TupleStructItemsNoRest &items_no_rest
= static_cast<AST::TupleStructItemsNoRest &> (items);
std::vector<std::unique_ptr<HIR::Pattern>> patterns;
- patterns.reserve (items_no_range.get_patterns ().size ());
+ patterns.reserve (items_no_rest.get_patterns ().size ());
- for (auto &inner_pattern : items_no_range.get_patterns ())
+ for (auto &inner_pattern : items_no_rest.get_patterns ())
patterns.emplace_back (
ASTLoweringPattern::translate (*inner_pattern));
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index e964318bf7c..751456ccc77 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -202,23 +202,65 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
{
case HIR::TupleStructItems::HAS_REST:
{
- // TODO
- rust_unreachable ();
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ size_t pattern_min_cap = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+ if (variant->num_fields () < pattern_min_cap)
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode::E0023,
+ "this pattern has %lu fields but the corresponding "
+ "tuple variant has %lu field",
+ (unsigned long) (pattern_min_cap),
+ (unsigned long) variant->num_fields ());
+ // we continue on to try and setup the types as best we can for
+ // type checking
+ }
+
+ // iterate the fields manually to set them up
+ size_t i = 0;
+ for (auto &pattern : items_has_rest.get_lower_patterns ())
+ {
+ if (i >= variant->num_fields ())
+ break;
+
+ TyTy::StructFieldType *field = variant->get_field_at_index (i++);
+ TyTy::BaseType *fty = field->get_field_type ();
+
+ // setup the type on this pattern type
+ context->insert_type (pattern->get_mappings (), fty);
+ TypeCheckPattern::Resolve (*pattern, fty);
+ }
+
+ i = variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ();
+ for (auto &pattern : items_has_rest.get_upper_patterns ())
+ {
+ if (i >= variant->num_fields ())
+ break;
+
+ TyTy::StructFieldType *field = variant->get_field_at_index (i++);
+ TyTy::BaseType *fty = field->get_field_type ();
+
+ // setup the type on this pattern type
+ context->insert_type (pattern->get_mappings (), fty);
+ TypeCheckPattern::Resolve (*pattern, fty);
+ }
}
break;
case HIR::TupleStructItems::NO_REST:
{
- HIR::TupleStructItemsNoRest &items_no_range
+ HIR::TupleStructItemsNoRest &items_no_rest
= static_cast<HIR::TupleStructItemsNoRest &> (items);
- if (items_no_range.get_patterns ().size () != variant->num_fields ())
+ if (items_no_rest.get_patterns ().size () != variant->num_fields ())
{
rust_error_at (
pattern.get_locus (), ErrorCode::E0023,
"this pattern has %lu fields but the corresponding "
"tuple variant has %lu field",
- (unsigned long) items_no_range.get_patterns ().size (),
+ (unsigned long) items_no_rest.get_patterns ().size (),
(unsigned long) variant->num_fields ());
// we continue on to try and setup the types as best we can for
// type checking
@@ -226,7 +268,7 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
// iterate the fields and set them up, I wish we had ZIP
size_t i = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
if (i >= variant->num_fields ())
break;
--
2.50.1