]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Implement lowering of AST::TupleStructItemsHasRest
authorYap Zhi Heng <yapzhhg@gmail.com>
Mon, 25 Aug 2025 12:16:09 +0000 (20:16 +0800)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:30:54 +0000 (21:30 +0100)
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 <yapzhhg@gmail.com>
gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
gcc/rust/hir/rust-ast-lower-pattern.cc
gcc/rust/typecheck/rust-hir-type-check-pattern.cc

index 13c54e34ccee3de0c779827e0b74a7fa263e1d14..f132e04ef7b733decfdedc6eab086549016fc1a4 100644 (file)
@@ -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:
index 00d1bc8c33e4cf6ff434c681d7db43405286522a..4250adbfbab68f6ac2af94230e876778b26c6a4c 100644 (file)
@@ -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));
 
index e964318bf7c24c7c55a87e07a7333fd664ab32a5..751456ccc7731a5d1776afb22119b82cf13bcbd1 100644 (file)
@@ -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;