Skip to content

Commit 51cfac1

Browse files
committed
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]>
1 parent 6311477 commit 51cfac1

File tree

3 files changed

+105
-17
lines changed

3 files changed

+105
-17
lines changed

gcc/rust/checks/errors/rust-hir-pattern-analysis.cc

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,25 +1212,52 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
12121212
{
12131213
case HIR::TupleStructItems::ItemType::NO_REST:
12141214
{
1215-
HIR::TupleStructItemsNoRest &multiple
1215+
HIR::TupleStructItemsNoRest &items_no_rest
12161216
= static_cast<HIR::TupleStructItemsNoRest &> (elems);
12171217

12181218
rust_assert (variant->get_fields ().size ()
1219-
== multiple.get_patterns ().size ());
1219+
== items_no_rest.get_patterns ().size ());
12201220

1221-
for (size_t i = 0; i < multiple.get_patterns ().size (); i++)
1221+
for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
12221222
{
12231223
fields.push_back (
1224-
lower_pattern (ctx, *multiple.get_patterns ().at (i),
1224+
lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
12251225
variant->get_fields ().at (i)->get_field_type ()));
12261226
}
12271227
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
12281228
}
12291229
break;
12301230
case HIR::TupleStructItems::ItemType::HAS_REST:
12311231
{
1232-
// TODO: ranged tuple struct items
1233-
rust_unreachable ();
1232+
HIR::TupleStructItemsHasRest &items_has_rest
1233+
= static_cast<HIR::TupleStructItemsHasRest &> (elems);
1234+
1235+
size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
1236+
+ items_has_rest.get_upper_patterns ().size ();
1237+
1238+
rust_assert (num_patterns <= variant->num_fields ());
1239+
1240+
size_t i = 0;
1241+
for (auto &pattern_member : items_has_rest.get_lower_patterns ())
1242+
{
1243+
fields.push_back (lower_pattern (
1244+
ctx, *pattern_member,
1245+
variant->get_fields ().at (i++)->get_field_type ()));
1246+
}
1247+
while (i < variant->num_fields ()
1248+
- items_has_rest.get_upper_patterns ().size ())
1249+
{
1250+
fields.push_back (
1251+
DeconstructedPat::make_wildcard (pattern.get_locus ()));
1252+
i++;
1253+
}
1254+
for (auto &pattern_member : items_has_rest.get_upper_patterns ())
1255+
{
1256+
fields.push_back (lower_pattern (
1257+
ctx, *pattern_member,
1258+
variant->get_fields ().at (i++)->get_field_type ()));
1259+
}
1260+
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
12341261
}
12351262
break;
12361263
default:

gcc/rust/hir/rust-ast-lower-pattern.cc

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,39 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
8383
{
8484
case AST::TupleStructItems::HAS_REST:
8585
{
86-
// TODO
87-
rust_unreachable ();
86+
AST::TupleStructItemsHasRest &items_has_rest
87+
= static_cast<AST::TupleStructItemsHasRest &> (items);
88+
89+
std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
90+
lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ());
91+
for (auto &pattern_member : items_has_rest.get_lower_patterns ())
92+
{
93+
lower_patterns.emplace_back (
94+
ASTLoweringPattern::translate (*pattern_member));
95+
}
96+
97+
std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
98+
upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ());
99+
for (auto &pattern_member : items_has_rest.get_upper_patterns ())
100+
{
101+
upper_patterns.emplace_back (
102+
ASTLoweringPattern::translate (*pattern_member));
103+
}
104+
105+
lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns),
106+
std::move (upper_patterns));
88107
}
89108
break;
90109

91110
case AST::TupleStructItems::NO_REST:
92111
{
93-
AST::TupleStructItemsNoRest &items_no_range
112+
AST::TupleStructItemsNoRest &items_no_rest
94113
= static_cast<AST::TupleStructItemsNoRest &> (items);
95114

96115
std::vector<std::unique_ptr<HIR::Pattern>> patterns;
97-
patterns.reserve (items_no_range.get_patterns ().size ());
116+
patterns.reserve (items_no_rest.get_patterns ().size ());
98117

99-
for (auto &inner_pattern : items_no_range.get_patterns ())
118+
for (auto &inner_pattern : items_no_rest.get_patterns ())
100119
patterns.emplace_back (
101120
ASTLoweringPattern::translate (*inner_pattern));
102121

gcc/rust/typecheck/rust-hir-type-check-pattern.cc

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,31 +202,73 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
202202
{
203203
case HIR::TupleStructItems::HAS_REST:
204204
{
205-
// TODO
206-
rust_unreachable ();
205+
HIR::TupleStructItemsHasRest &items_has_rest
206+
= static_cast<HIR::TupleStructItemsHasRest &> (items);
207+
size_t pattern_min_cap = items_has_rest.get_lower_patterns ().size ()
208+
+ items_has_rest.get_upper_patterns ().size ();
209+
if (variant->num_fields () < pattern_min_cap)
210+
{
211+
rust_error_at (pattern.get_locus (), ErrorCode::E0023,
212+
"this pattern has %lu fields but the corresponding "
213+
"tuple variant has %lu field",
214+
(unsigned long) (pattern_min_cap),
215+
(unsigned long) variant->num_fields ());
216+
// we continue on to try and setup the types as best we can for
217+
// type checking
218+
}
219+
220+
// iterate the fields manually to set them up
221+
size_t i = 0;
222+
for (auto &pattern : items_has_rest.get_lower_patterns ())
223+
{
224+
if (i >= variant->num_fields ())
225+
break;
226+
227+
TyTy::StructFieldType *field = variant->get_field_at_index (i++);
228+
TyTy::BaseType *fty = field->get_field_type ();
229+
230+
// setup the type on this pattern type
231+
context->insert_type (pattern->get_mappings (), fty);
232+
TypeCheckPattern::Resolve (*pattern, fty);
233+
}
234+
235+
i = variant->num_fields ()
236+
- items_has_rest.get_upper_patterns ().size ();
237+
for (auto &pattern : items_has_rest.get_upper_patterns ())
238+
{
239+
if (i >= variant->num_fields ())
240+
break;
241+
242+
TyTy::StructFieldType *field = variant->get_field_at_index (i++);
243+
TyTy::BaseType *fty = field->get_field_type ();
244+
245+
// setup the type on this pattern type
246+
context->insert_type (pattern->get_mappings (), fty);
247+
TypeCheckPattern::Resolve (*pattern, fty);
248+
}
207249
}
208250
break;
209251

210252
case HIR::TupleStructItems::NO_REST:
211253
{
212-
HIR::TupleStructItemsNoRest &items_no_range
254+
HIR::TupleStructItemsNoRest &items_no_rest
213255
= static_cast<HIR::TupleStructItemsNoRest &> (items);
214256

215-
if (items_no_range.get_patterns ().size () != variant->num_fields ())
257+
if (items_no_rest.get_patterns ().size () != variant->num_fields ())
216258
{
217259
rust_error_at (
218260
pattern.get_locus (), ErrorCode::E0023,
219261
"this pattern has %lu fields but the corresponding "
220262
"tuple variant has %lu field",
221-
(unsigned long) items_no_range.get_patterns ().size (),
263+
(unsigned long) items_no_rest.get_patterns ().size (),
222264
(unsigned long) variant->num_fields ());
223265
// we continue on to try and setup the types as best we can for
224266
// type checking
225267
}
226268

227269
// iterate the fields and set them up, I wish we had ZIP
228270
size_t i = 0;
229-
for (auto &pattern : items_no_range.get_patterns ())
271+
for (auto &pattern : items_no_rest.get_patterns ())
230272
{
231273
if (i >= variant->num_fields ())
232274
break;

0 commit comments

Comments
 (0)