libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / backend / rust-compile-pattern.cc
blob1a32f02c3ea316fb56df4b1a097d8995c27e939f
1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
8 // version.
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
19 #include "rust-compile-pattern.h"
20 #include "rust-compile-expr.h"
21 #include "rust-compile-resolve-path.h"
22 #include "rust-constexpr.h"
23 #include "rust-compile-type.h"
25 namespace Rust {
26 namespace Compile {
28 void
29 CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern)
31 // lookup the type
32 TyTy::BaseType *lookup = nullptr;
33 bool ok
34 = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
35 &lookup);
36 rust_assert (ok);
38 // this must be an enum
39 // TODO: might not be
40 rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
41 TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
42 rust_assert (adt->is_enum ());
44 // lookup the variant
45 HirId variant_id;
46 ok = ctx->get_tyctx ()->lookup_variant_definition (
47 pattern.get_mappings ().get_hirid (), &variant_id);
48 rust_assert (ok);
50 TyTy::VariantDef *variant = nullptr;
51 ok = adt->lookup_variant_by_id (variant_id, &variant);
52 rust_assert (ok);
54 // find discriminant field of scrutinee
55 tree scrutinee_record_expr
56 = Backend::struct_field_expression (match_scrutinee_expr, 0,
57 pattern.get_locus ());
58 tree scrutinee_expr_qualifier_expr
59 = Backend::struct_field_expression (scrutinee_record_expr, 0,
60 pattern.get_locus ());
62 // must be enum
63 match_scrutinee_expr = scrutinee_expr_qualifier_expr;
65 HIR::Expr *discrim_expr = variant->get_discriminant ();
66 tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
68 check_expr
69 = Backend::comparison_expression (ComparisonOperator::EQUAL,
70 match_scrutinee_expr, discrim_expr_node,
71 pattern.get_locus ());
74 void
75 CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
77 // Compile the literal
78 HIR::LiteralExpr *litexpr
79 = new HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (),
80 pattern.get_locus (),
81 std::vector<AST::Attribute> ());
83 // Note: Floating point literals are currently accepted but will likely be
84 // forbidden in LiteralPatterns in a future version of Rust.
85 // See: https://github.com/rust-lang/rust/issues/41620
86 // For now, we cannot compile them anyway as CASE_LABEL_EXPR does not support
87 // floating point types.
88 if (pattern.get_literal ().get_lit_type () == HIR::Literal::LitType::FLOAT)
90 rust_sorry_at (pattern.get_locus (), "floating-point literal in pattern");
93 tree lit = CompileExpr::Compile (litexpr, ctx);
95 check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL,
96 match_scrutinee_expr, lit,
97 pattern.get_locus ());
100 static tree
101 compile_range_pattern_bound (HIR::RangePatternBound *bound,
102 Analysis::NodeMapping mappings, location_t locus,
103 Context *ctx)
105 tree result = NULL_TREE;
106 switch (bound->get_bound_type ())
108 case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
109 HIR::RangePatternBoundLiteral &ref
110 = *static_cast<HIR::RangePatternBoundLiteral *> (bound);
112 HIR::LiteralExpr *litexpr
113 = new HIR::LiteralExpr (mappings, ref.get_literal (), locus,
114 std::vector<AST::Attribute> ());
116 result = CompileExpr::Compile (litexpr, ctx);
118 break;
120 case HIR::RangePatternBound::RangePatternBoundType::PATH: {
121 HIR::RangePatternBoundPath &ref
122 = *static_cast<HIR::RangePatternBoundPath *> (bound);
124 result = ResolvePathRef::Compile (ref.get_path (), ctx);
126 // If the path resolves to a const expression, fold it.
127 result = fold_expr (result);
129 break;
131 case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
132 HIR::RangePatternBoundQualPath &ref
133 = *static_cast<HIR::RangePatternBoundQualPath *> (bound);
135 result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
137 // If the path resolves to a const expression, fold it.
138 result = fold_expr (result);
142 return result;
145 void
146 CompilePatternCheckExpr::visit (HIR::RangePattern &pattern)
148 tree upper = compile_range_pattern_bound (pattern.get_upper_bound ().get (),
149 pattern.get_mappings (),
150 pattern.get_locus (), ctx);
151 tree lower = compile_range_pattern_bound (pattern.get_lower_bound ().get (),
152 pattern.get_mappings (),
153 pattern.get_locus (), ctx);
155 tree check_lower
156 = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL,
157 match_scrutinee_expr, lower,
158 pattern.get_locus ());
159 tree check_upper
160 = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL,
161 match_scrutinee_expr, upper,
162 pattern.get_locus ());
163 check_expr = Backend::arithmetic_or_logical_expression (
164 ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper,
165 pattern.get_locus ());
168 void
169 CompilePatternCheckExpr::visit (HIR::ReferencePattern &pattern)
171 match_scrutinee_expr
172 = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
173 pattern.get_referenced_pattern ()->accept_vis (*this);
176 void
177 CompilePatternCheckExpr::visit (HIR::AltPattern &pattern)
179 auto &alts = pattern.get_alts ();
181 check_expr = CompilePatternCheckExpr::Compile (alts.at (0).get (),
182 match_scrutinee_expr, ctx);
183 auto end = alts.end ();
184 for (auto i = alts.begin () + 1; i != end; i++)
186 tree next_expr
187 = CompilePatternCheckExpr::Compile (i->get (), match_scrutinee_expr,
188 ctx);
189 check_expr = Backend::arithmetic_or_logical_expression (
190 ArithmeticOrLogicalOperator::BITWISE_OR, check_expr, next_expr,
191 (*i)->get_locus ());
195 void
196 CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
198 // lookup the type
199 TyTy::BaseType *lookup = nullptr;
200 bool ok = ctx->get_tyctx ()->lookup_type (
201 pattern.get_path ().get_mappings ().get_hirid (), &lookup);
202 rust_assert (ok);
204 // this might be an enum
205 rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
206 TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
208 rust_assert (adt->number_of_variants () > 0);
209 TyTy::VariantDef *variant = nullptr;
210 if (adt->is_enum ())
212 // lookup the variant
213 HirId variant_id;
214 ok = ctx->get_tyctx ()->lookup_variant_definition (
215 pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
216 rust_assert (ok);
218 int variant_index = 0;
219 ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
220 rust_assert (ok);
222 // find expected discriminant
223 // // need to access qualifier the field, if we use QUAL_UNION_TYPE this
224 // // would be DECL_QUALIFIER i think. For now this will just access the
225 // // first record field and its respective qualifier because it will
226 // // always be set because this is all a big special union
227 HIR::Expr *discrim_expr = variant->get_discriminant ();
228 tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
230 // find discriminant field of scrutinee
231 tree scrutinee_record_expr
232 = Backend::struct_field_expression (match_scrutinee_expr, variant_index,
233 pattern.get_path ().get_locus ());
234 tree scrutinee_expr_qualifier_expr
235 = Backend::struct_field_expression (scrutinee_record_expr, 0,
236 pattern.get_path ().get_locus ());
238 check_expr
239 = Backend::comparison_expression (ComparisonOperator::EQUAL,
240 scrutinee_expr_qualifier_expr,
241 discrim_expr_node,
242 pattern.get_path ().get_locus ());
244 match_scrutinee_expr = scrutinee_record_expr;
246 else
248 variant = adt->get_variants ().at (0);
249 check_expr = boolean_true_node;
252 auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
253 for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
255 switch (field->get_item_type ())
257 case HIR::StructPatternField::ItemType::TUPLE_PAT: {
258 // TODO
259 rust_unreachable ();
261 break;
263 case HIR::StructPatternField::ItemType::IDENT_PAT: {
264 HIR::StructPatternFieldIdentPat &ident
265 = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());
267 size_t offs = 0;
268 ok = variant->lookup_field (ident.get_identifier ().as_string (),
269 nullptr, &offs);
270 rust_assert (ok);
272 // we may be offsetting by + 1 here since the first field in the
273 // record is always the discriminator
274 offs += adt->is_enum ();
275 tree field_expr
276 = Backend::struct_field_expression (match_scrutinee_expr, offs,
277 ident.get_locus ());
279 tree check_expr_sub
280 = CompilePatternCheckExpr::Compile (ident.get_pattern ().get (),
281 field_expr, ctx);
282 check_expr = Backend::arithmetic_or_logical_expression (
283 ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
284 check_expr_sub, ident.get_pattern ()->get_locus ());
286 break;
288 case HIR::StructPatternField::ItemType::IDENT: {
289 // ident pattern always matches - do nothing
291 break;
296 void
297 CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
299 size_t tuple_field_index;
301 // lookup the type
302 TyTy::BaseType *lookup = nullptr;
303 bool ok = ctx->get_tyctx ()->lookup_type (
304 pattern.get_path ().get_mappings ().get_hirid (), &lookup);
305 rust_assert (ok);
307 // this might be an enum
308 rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
309 TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
311 rust_assert (adt->number_of_variants () > 0);
312 TyTy::VariantDef *variant = nullptr;
313 if (adt->is_enum ())
315 // lookup the variant
316 HirId variant_id;
317 ok = ctx->get_tyctx ()->lookup_variant_definition (
318 pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
319 rust_assert (ok);
321 int variant_index = 0;
322 ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
323 rust_assert (ok);
325 // find expected discriminant
326 HIR::Expr *discrim_expr = variant->get_discriminant ();
327 tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
329 // find discriminant field of scrutinee
330 tree scrutinee_record_expr
331 = Backend::struct_field_expression (match_scrutinee_expr, variant_index,
332 pattern.get_path ().get_locus ());
333 tree scrutinee_expr_qualifier_expr
334 = Backend::struct_field_expression (scrutinee_record_expr, 0,
335 pattern.get_path ().get_locus ());
337 check_expr
338 = Backend::comparison_expression (ComparisonOperator::EQUAL,
339 scrutinee_expr_qualifier_expr,
340 discrim_expr_node,
341 pattern.get_path ().get_locus ());
343 match_scrutinee_expr = scrutinee_record_expr;
344 // we are offsetting by + 1 here since the first field in the record
345 // is always the discriminator
346 tuple_field_index = 1;
348 else
350 variant = adt->get_variants ().at (0);
351 check_expr = boolean_true_node;
352 tuple_field_index = 0;
355 std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items ();
356 switch (items->get_item_type ())
358 case HIR::TupleStructItems::RANGED: {
359 // TODO
360 rust_unreachable ();
362 break;
364 case HIR::TupleStructItems::MULTIPLE: {
365 HIR::TupleStructItemsNoRange &items_no_range
366 = static_cast<HIR::TupleStructItemsNoRange &> (*items.get ());
368 rust_assert (items_no_range.get_patterns ().size ()
369 == variant->num_fields ());
371 for (auto &pattern : items_no_range.get_patterns ())
373 tree field_expr
374 = Backend::struct_field_expression (match_scrutinee_expr,
375 tuple_field_index++,
376 pattern->get_locus ());
378 tree check_expr_sub
379 = CompilePatternCheckExpr::Compile (pattern.get (), field_expr,
380 ctx);
381 check_expr = Backend::arithmetic_or_logical_expression (
382 ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
383 check_expr_sub, pattern->get_locus ());
386 break;
390 void
391 CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
393 check_expr = boolean_true_node;
395 switch (pattern.get_items ()->get_item_type ())
397 case HIR::TuplePatternItems::RANGED: {
398 // TODO
399 gcc_unreachable ();
401 break;
403 case HIR::TuplePatternItems::MULTIPLE: {
404 auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
405 *pattern.get_items ());
406 size_t tuple_field_index = 0;
408 for (auto &pat : items.get_patterns ())
410 tree field_expr
411 = Backend::struct_field_expression (match_scrutinee_expr,
412 tuple_field_index++,
413 pat->get_locus ());
415 tree check_expr_sub
416 = CompilePatternCheckExpr::Compile (pat.get (), field_expr, ctx);
417 check_expr = Backend::arithmetic_or_logical_expression (
418 ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
419 check_expr_sub, pat->get_locus ());
425 // setup the bindings
427 void
428 CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
430 // lookup the type
431 TyTy::BaseType *lookup = nullptr;
432 bool ok = ctx->get_tyctx ()->lookup_type (
433 pattern.get_path ().get_mappings ().get_hirid (), &lookup);
434 rust_assert (ok);
436 // this must be an enum
437 rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
438 TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
439 rust_assert (adt->number_of_variants () > 0);
441 int variant_index = 0;
442 TyTy::VariantDef *variant = adt->get_variants ().at (0);
443 if (adt->is_enum ())
445 HirId variant_id = UNKNOWN_HIRID;
446 bool ok = ctx->get_tyctx ()->lookup_variant_definition (
447 pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
448 rust_assert (ok);
450 ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
451 rust_assert (ok);
454 rust_assert (variant->get_variant_type ()
455 == TyTy::VariantDef::VariantType::TUPLE);
457 std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items ();
458 switch (items->get_item_type ())
460 case HIR::TupleStructItems::RANGED: {
461 // TODO
462 rust_unreachable ();
464 break;
466 case HIR::TupleStructItems::MULTIPLE: {
467 HIR::TupleStructItemsNoRange &items_no_range
468 = static_cast<HIR::TupleStructItemsNoRange &> (*items.get ());
470 rust_assert (items_no_range.get_patterns ().size ()
471 == variant->num_fields ());
473 if (adt->is_enum ())
475 // we are offsetting by + 1 here since the first field in the record
476 // is always the discriminator
477 size_t tuple_field_index = 1;
478 for (auto &pattern : items_no_range.get_patterns ())
480 tree variant_accessor
481 = Backend::struct_field_expression (match_scrutinee_expr,
482 variant_index,
483 pattern->get_locus ());
485 tree binding
486 = Backend::struct_field_expression (variant_accessor,
487 tuple_field_index++,
488 pattern->get_locus ());
490 ctx->insert_pattern_binding (
491 pattern->get_mappings ().get_hirid (), binding);
494 else
496 size_t tuple_field_index = 0;
497 for (auto &pattern : items_no_range.get_patterns ())
499 tree variant_accessor = match_scrutinee_expr;
501 tree binding
502 = Backend::struct_field_expression (variant_accessor,
503 tuple_field_index++,
504 pattern->get_locus ());
506 ctx->insert_pattern_binding (
507 pattern->get_mappings ().get_hirid (), binding);
511 break;
515 void
516 CompilePatternBindings::visit (HIR::StructPattern &pattern)
518 // lookup the type
519 TyTy::BaseType *lookup = nullptr;
520 bool ok = ctx->get_tyctx ()->lookup_type (
521 pattern.get_path ().get_mappings ().get_hirid (), &lookup);
522 rust_assert (ok);
524 // this must be an enum
525 rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
526 TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
527 rust_assert (adt->number_of_variants () > 0);
529 int variant_index = 0;
530 TyTy::VariantDef *variant = adt->get_variants ().at (0);
531 if (adt->is_enum ())
533 HirId variant_id = UNKNOWN_HIRID;
534 bool ok = ctx->get_tyctx ()->lookup_variant_definition (
535 pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
536 rust_assert (ok);
538 ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
539 rust_assert (ok);
542 rust_assert (variant->get_variant_type ()
543 == TyTy::VariantDef::VariantType::STRUCT);
545 auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
546 for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
548 switch (field->get_item_type ())
550 case HIR::StructPatternField::ItemType::TUPLE_PAT: {
551 // TODO
552 rust_unreachable ();
554 break;
556 case HIR::StructPatternField::ItemType::IDENT_PAT: {
557 // TODO
558 rust_unreachable ();
560 break;
562 case HIR::StructPatternField::ItemType::IDENT: {
563 HIR::StructPatternFieldIdent &ident
564 = static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
566 size_t offs = 0;
567 ok = variant->lookup_field (ident.get_identifier ().as_string (),
568 nullptr, &offs);
569 rust_assert (ok);
571 tree binding = error_mark_node;
572 if (adt->is_enum ())
574 tree variant_accessor
575 = Backend::struct_field_expression (match_scrutinee_expr,
576 variant_index,
577 ident.get_locus ());
579 // we are offsetting by + 1 here since the first field in the
580 // record is always the discriminator
581 binding = Backend::struct_field_expression (variant_accessor,
582 offs + 1,
583 ident.get_locus ());
585 else
587 tree variant_accessor = match_scrutinee_expr;
588 binding
589 = Backend::struct_field_expression (variant_accessor, offs,
590 ident.get_locus ());
593 ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
594 binding);
596 break;
601 void
602 CompilePatternBindings::visit (HIR::ReferencePattern &pattern)
604 tree derefed
605 = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
607 CompilePatternBindings::Compile (pattern.get_referenced_pattern ().get (),
608 derefed, ctx);
611 void
612 CompilePatternBindings::visit (HIR::IdentifierPattern &pattern)
614 ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (),
615 match_scrutinee_expr);
618 void
619 CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
621 Bvariable *var = nullptr;
622 rust_assert (
623 ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var));
625 auto fnctx = ctx->peek_fn ();
626 if (ty->is_unit ())
628 ctx->add_statement (init_expr);
630 auto unit_type_init_expr = unit_expression (ctx, rval_locus);
631 auto s = Backend::init_statement (fnctx.fndecl, var, unit_type_init_expr);
632 ctx->add_statement (s);
634 else
636 auto s = Backend::init_statement (fnctx.fndecl, var, init_expr);
637 ctx->add_statement (s);
641 void
642 CompilePatternLet::visit (HIR::WildcardPattern &pattern)
644 tree init_stmt = NULL;
645 tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
647 Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, stmt_type,
648 init_expr, false, pattern.get_locus (),
649 &init_stmt);
651 ctx->add_statement (init_stmt);
654 void
655 CompilePatternLet::visit (HIR::TuplePattern &pattern)
657 rust_assert (pattern.has_tuple_pattern_items ());
659 tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
660 tree init_stmt;
661 Bvariable *tmp_var
662 = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
663 tuple_type, init_expr, false,
664 pattern.get_locus (), &init_stmt);
665 tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ());
666 ctx->add_statement (init_stmt);
668 switch (pattern.get_items ()->get_item_type ())
670 case HIR::TuplePatternItems::ItemType::RANGED: {
671 size_t tuple_idx = 0;
672 auto &items
673 = static_cast<HIR::TuplePatternItemsRanged &> (*pattern.get_items ());
675 auto &items_lower = items.get_lower_patterns ();
676 auto &items_upper = items.get_upper_patterns ();
678 for (auto &sub : items_lower)
680 TyTy::BaseType *ty_sub = nullptr;
681 HirId sub_id = sub->get_mappings ().get_hirid ();
682 bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
683 rust_assert (ok);
685 tree sub_init
686 = Backend::struct_field_expression (access_expr, tuple_idx,
687 sub->get_locus ());
688 CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
689 rval_locus, ctx);
690 tuple_idx++;
693 rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
694 tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
695 - items_upper.size ();
697 for (auto &sub : items_upper)
699 TyTy::BaseType *ty_sub = nullptr;
700 HirId sub_id = sub->get_mappings ().get_hirid ();
701 bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
702 rust_assert (ok);
704 tree sub_init
705 = Backend::struct_field_expression (access_expr, tuple_idx,
706 sub->get_locus ());
707 CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
708 rval_locus, ctx);
709 tuple_idx++;
712 return;
714 case HIR::TuplePatternItems::ItemType::MULTIPLE: {
715 size_t tuple_idx = 0;
716 auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
717 *pattern.get_items ());
719 for (auto &sub : items.get_patterns ())
721 TyTy::BaseType *ty_sub = nullptr;
722 HirId sub_id = sub->get_mappings ().get_hirid ();
723 bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
724 rust_assert (ok);
726 tree sub_init
727 = Backend::struct_field_expression (access_expr, tuple_idx,
728 sub->get_locus ());
729 CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
730 rval_locus, ctx);
731 tuple_idx++;
734 return;
736 default: {
737 rust_unreachable ();
742 } // namespace Compile
743 } // namespace Rust