https://gcc.gnu.org/g:81c861171c14d969fdf2ba2cf3cdf1f300b98148
commit r16-4880-g81c861171c14d969fdf2ba2cf3cdf1f300b98148 Author: Yap Zhi Heng <[email protected]> Date: Mon Aug 25 20:16:09 2025 +0800 gccrs: Implement lowering of AST::TupleStructItemsHasRest 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]> Diff: --- .../checks/errors/rust-hir-pattern-analysis.cc | 39 +++++++++++++--- gcc/rust/hir/rust-ast-lower-pattern.cc | 29 ++++++++++-- gcc/rust/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 13c54e34ccee..f132e04ef7b7 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 00d1bc8c33e4..4250adbfbab6 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 e964318bf7c2..751456ccc773 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;
