LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-pattern.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.7 % 607 520
Test Date: 2026-02-28 14:20:25 Functions: 67.7 % 31 21
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       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.
       9              : 
      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.
      14              : 
      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/>.
      18              : 
      19              : #include "rust-hir-type-check-pattern.h"
      20              : #include "rust-hir-pattern.h"
      21              : #include "rust-hir-type-check-expr.h"
      22              : #include "rust-token.h"
      23              : #include "rust-type-util.h"
      24              : #include "rust-immutable-name-resolution-context.h"
      25              : #include "rust-tyty.h"
      26              : #include "tree.h"
      27              : 
      28              : namespace Rust {
      29              : namespace Resolver {
      30              : 
      31        43746 : TypeCheckPattern::TypeCheckPattern (TyTy::BaseType *parent)
      32        43746 :   : TypeCheckBase (), parent (parent), infered (new TyTy::ErrorType (0))
      33        43746 : {}
      34              : 
      35              : TyTy::BaseType *
      36        43746 : TypeCheckPattern::Resolve (HIR::Pattern &pattern, TyTy::BaseType *parent)
      37              : {
      38        43746 :   TypeCheckPattern resolver (parent);
      39        43746 :   pattern.accept_vis (resolver);
      40              : 
      41        43746 :   if (resolver.infered == nullptr)
      42            0 :     return new TyTy::ErrorType (pattern.get_mappings ().get_hirid ());
      43              : 
      44        43746 :   resolver.context->insert_type (pattern.get_mappings (), resolver.infered);
      45        43746 :   return resolver.infered;
      46        43746 : }
      47              : 
      48              : void
      49         1086 : TypeCheckPattern::visit (HIR::PathInExpression &pattern)
      50              : {
      51              :   // Pattern must be enum variants, sturcts, constants, or associated constansts
      52         1086 :   TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern);
      53              : 
      54         1086 :   NodeId ref_node_id = UNKNOWN_NODEID;
      55         1086 :   bool maybe_item = false;
      56              : 
      57         1086 :   auto &nr_ctx
      58         1086 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
      59              : 
      60         1086 :   if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
      61              :     {
      62         1084 :       ref_node_id = *id;
      63         1084 :       maybe_item = true;
      64              :     }
      65              : 
      66         1086 :   bool path_is_const_item = false;
      67              : 
      68         1086 :   if (maybe_item)
      69              :     {
      70         1084 :       tl::optional<HirId> definition_id
      71         1084 :         = mappings.lookup_node_to_hir (ref_node_id);
      72         1084 :       rust_assert (definition_id.has_value ());
      73         1084 :       HirId def_id = definition_id.value ();
      74              : 
      75         1084 :       tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
      76              :       // If the path refrerences an item, it must be constants or structs.
      77         1084 :       if (hir_item.has_value ())
      78              :         {
      79            5 :           HIR::Item *item = hir_item.value ();
      80            5 :           if (item->get_item_kind () == HIR::Item::ItemKind::Constant)
      81              :             {
      82              :               path_is_const_item = true;
      83              :             }
      84            4 :           else if (item->get_item_kind () != HIR::Item::ItemKind::Struct)
      85              :             {
      86            4 :               HIR::Item *item = hir_item.value ();
      87            4 :               std::string item_kind
      88            4 :                 = HIR::Item::item_kind_string (item->get_item_kind ());
      89              : 
      90            4 :               std::string path_buf;
      91           12 :               for (size_t i = 0; i < pattern.get_segments ().size (); i++)
      92              :                 {
      93            8 :                   HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
      94           16 :                   path_buf += seg.to_string ();
      95            8 :                   if (i != pattern.get_segments ().size () - 1)
      96            4 :                     path_buf += "::";
      97              :                 }
      98              : 
      99            4 :               rich_location rich_locus (
     100            4 :                 line_table, pattern.get_final_segment ().get_locus ());
     101            4 :               rich_locus.add_fixit_replace (
     102              :                 "not a unit struct, unit variant or constant");
     103            4 :               rust_error_at (rich_locus, ErrorCode::E0532,
     104              :                              "expected unit struct, unit variant or constant, "
     105              :                              "found %s %<%s%>",
     106              :                              item_kind.c_str (), path_buf.c_str ());
     107            4 :               return;
     108            4 :             }
     109              :         }
     110              :     }
     111              : 
     112              :   // If the path is a constructor, it must be a unit struct or unit variants.
     113         1082 :   if (!path_is_const_item && pattern_ty->get_kind () == TyTy::TypeKind::ADT)
     114              :     {
     115         1079 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (pattern_ty);
     116         1079 :       rust_assert (adt->get_variants ().size () > 0);
     117              : 
     118         1079 :       TyTy::VariantDef *variant = adt->get_variants ().at (0);
     119         1079 :       if (adt->is_enum ())
     120              :         {
     121         1079 :           HirId variant_id = UNKNOWN_HIRID;
     122         1079 :           bool ok = context->lookup_variant_definition (
     123         1079 :             pattern.get_mappings ().get_hirid (), &variant_id);
     124         1079 :           rust_assert (ok);
     125              : 
     126         1079 :           ok = adt->lookup_variant_by_id (variant_id, &variant);
     127         1079 :           rust_assert (ok);
     128              :         }
     129              : 
     130         1079 :       if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
     131              :         {
     132            3 :           std::string variant_type = TyTy::VariantDef::variant_type_string (
     133            3 :             variant->get_variant_type ());
     134              : 
     135            3 :           rich_location rich_locus (line_table,
     136            3 :                                     pattern.get_final_segment ().get_locus ());
     137            3 :           rich_locus.add_fixit_replace (
     138              :             "not a unit struct, unit variant or constatnt");
     139            3 :           rust_error_at (rich_locus, ErrorCode::E0532,
     140              :                          "expected unit struct, unit variant or constant, "
     141              :                          "found %s variant %<%s::%s%>",
     142            6 :                          variant_type.c_str (), adt->get_name ().c_str (),
     143            3 :                          variant->get_identifier ().c_str ());
     144            3 :           return;
     145            3 :         }
     146              : 
     147         1076 :       infered = pattern_ty;
     148              :     }
     149              : }
     150              : 
     151              : void
     152         1003 : TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
     153              : {
     154         1003 :   TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
     155         1003 :   if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
     156              :     {
     157            2 :       rust_error_at (
     158            2 :         pattern.get_locus (), ErrorCode::E0532,
     159              :         "expected tuple struct or tuple variant, found function %qs",
     160            2 :         pattern_ty->get_name ().c_str ());
     161            6 :       return;
     162              :     }
     163              : 
     164         1001 :   infered = pattern_ty;
     165         1001 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
     166              : 
     167         1001 :   TyTy::VariantDef *variant = nullptr;
     168         1001 :   if (adt->is_enum ())
     169              :     {
     170          939 :       HirId variant_id = UNKNOWN_HIRID;
     171          939 :       bool ok = context->lookup_variant_definition (
     172          939 :         pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
     173          939 :       if (!ok)
     174              :         {
     175            3 :           rust_error_at (
     176            3 :             pattern.get_locus (), ErrorCode::E0532,
     177              :             "expected tuple struct or tuple variant, found enum %qs",
     178            3 :             pattern_ty->get_name ().c_str ());
     179            3 :           return;
     180              :         }
     181              : 
     182          936 :       ok = adt->lookup_variant_by_id (variant_id, &variant);
     183          936 :       rust_assert (ok);
     184              :     }
     185              :   else
     186              :     {
     187           62 :       rust_assert (adt->number_of_variants () > 0);
     188           62 :       variant = adt->get_variants ().at (0);
     189              :     }
     190              : 
     191          998 :   rust_assert (variant != nullptr);
     192              : 
     193              :   // error[E0532]: expected tuple struct or tuple variant, found struct
     194              :   // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
     195          998 :   if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
     196              :     {
     197            1 :       std::string variant_type
     198            1 :         = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
     199              : 
     200            1 :       rich_location rich_locus (line_table, pattern.get_locus ());
     201            1 :       rich_locus.add_fixit_replace ("not a tuple struct or tuple variant");
     202            1 :       rust_error_at (
     203              :         rich_locus, ErrorCode::E0164,
     204              :         "expected tuple struct or tuple variant, found %s variant %<%s::%s%>",
     205            2 :         variant_type.c_str (), adt->get_name ().c_str (),
     206            1 :         variant->get_identifier ().c_str ());
     207            1 :       return;
     208            1 :     }
     209              : 
     210              :   // check the elements
     211              :   // error[E0023]: this pattern has 2 fields, but the corresponding tuple
     212              :   // variant has 1 field
     213              :   // error[E0023]: this pattern has 0 fields, but the corresponding tuple
     214              :   // variant has 1 field
     215              : 
     216          997 :   auto &items = pattern.get_items ();
     217          997 :   switch (items.get_item_type ())
     218              :     {
     219           38 :     case HIR::TupleStructItems::HAS_REST:
     220           38 :       {
     221           38 :         HIR::TupleStructItemsHasRest &items_has_rest
     222              :           = static_cast<HIR::TupleStructItemsHasRest &> (items);
     223           38 :         auto &lower_patterns = items_has_rest.get_lower_patterns ();
     224           38 :         auto &upper_patterns = items_has_rest.get_upper_patterns ();
     225           38 :         size_t pattern_min_cap
     226           38 :           = lower_patterns.size () + upper_patterns.size ();
     227           38 :         if (variant->num_fields () < pattern_min_cap)
     228              :           {
     229            2 :             if (!lower_patterns.empty ())
     230              :               {
     231              :                 // TODO initialize rich_locus with loc of ADT definition instead
     232            1 :                 rich_location rich_locus (line_table,
     233            1 :                                           lower_patterns[0]->get_locus ());
     234            3 :                 for (auto &pattern : lower_patterns)
     235              :                   {
     236            2 :                     if (pattern == lower_patterns[0])
     237            1 :                       continue;
     238            1 :                     rich_locus.add_range (pattern->get_locus (),
     239              :                                           SHOW_RANGE_WITH_CARET);
     240              :                   }
     241            3 :                 for (auto &pattern : upper_patterns)
     242              :                   {
     243            2 :                     rich_locus.add_range (pattern->get_locus (),
     244              :                                           SHOW_RANGE_WITH_CARET);
     245              :                   }
     246            3 :                 rust_error_at (rich_locus, ErrorCode::E0023,
     247              :                                "this pattern has %lu %s but the corresponding "
     248              :                                "tuple variant has %lu %s",
     249              :                                (unsigned long) (pattern_min_cap),
     250              :                                pattern_min_cap == 1 ? "field" : "fields",
     251            1 :                                (unsigned long) variant->num_fields (),
     252            1 :                                variant->num_fields () == 1 ? "field"
     253              :                                                            : "fields");
     254            1 :               }
     255              :             else
     256              :               {
     257              :                 // TODO initialize rich_locus with loc of ADT definition instead
     258            1 :                 rich_location rich_locus (line_table,
     259            1 :                                           upper_patterns[0]->get_locus ());
     260            4 :                 for (auto &pattern : upper_patterns)
     261              :                   {
     262            3 :                     if (pattern == upper_patterns[0])
     263            1 :                       continue;
     264            2 :                     rich_locus.add_range (pattern->get_locus (),
     265              :                                           SHOW_RANGE_WITH_CARET);
     266              :                   }
     267            3 :                 rust_error_at (rich_locus, ErrorCode::E0023,
     268              :                                "this pattern has %lu %s but the corresponding "
     269              :                                "tuple variant has %lu %s",
     270              :                                (unsigned long) (pattern_min_cap),
     271              :                                pattern_min_cap == 1 ? "field" : "fields",
     272            1 :                                (unsigned long) variant->num_fields (),
     273            1 :                                variant->num_fields () == 1 ? "field"
     274              :                                                            : "fields");
     275            1 :               }
     276              :             // we continue on to try and setup the types as best we can for
     277              :             // type checking
     278              :           }
     279              : 
     280              :         // iterate the fields manually to set them up
     281           38 :         size_t i = 0;
     282           69 :         for (auto &pattern : lower_patterns)
     283              :           {
     284           31 :             if (i >= variant->num_fields ())
     285              :               break;
     286              : 
     287           31 :             TyTy::StructFieldType *field = variant->get_field_at_index (i++);
     288           31 :             TyTy::BaseType *fty = field->get_field_type ();
     289              : 
     290              :             // setup the type on this pattern type
     291           31 :             context->insert_type (pattern->get_mappings (), fty);
     292           31 :             TypeCheckPattern::Resolve (*pattern, fty);
     293              :           }
     294              : 
     295           38 :         i = variant->num_fields () - upper_patterns.size ();
     296           54 :         for (auto &pattern : upper_patterns)
     297              :           {
     298           17 :             if (i >= variant->num_fields ())
     299              :               break;
     300              : 
     301           16 :             TyTy::StructFieldType *field = variant->get_field_at_index (i++);
     302           16 :             TyTy::BaseType *fty = field->get_field_type ();
     303              : 
     304              :             // setup the type on this pattern type
     305           16 :             context->insert_type (pattern->get_mappings (), fty);
     306           16 :             TypeCheckPattern::Resolve (*pattern, fty);
     307              :           }
     308              :       }
     309              :       break;
     310              : 
     311          959 :     case HIR::TupleStructItems::NO_REST:
     312          959 :       {
     313          959 :         HIR::TupleStructItemsNoRest &items_no_rest
     314              :           = static_cast<HIR::TupleStructItemsNoRest &> (items);
     315          959 :         auto &patterns = items_no_rest.get_patterns ();
     316              : 
     317          959 :         if (patterns.size () != variant->num_fields ())
     318              :           {
     319            2 :             if (patterns.empty ())
     320              :               {
     321            0 :                 rust_error_at (pattern.get_locus (), ErrorCode::E0023,
     322              :                                "this pattern has %lu %s but the corresponding "
     323              :                                "tuple variant has %lu %s",
     324            0 :                                (unsigned long) patterns.size (),
     325            0 :                                patterns.size () == 1 ? "field" : "fields",
     326            0 :                                (unsigned long) variant->num_fields (),
     327            0 :                                variant->num_fields () == 1 ? "field"
     328              :                                                            : "fields");
     329              :               }
     330              :             else
     331              :               {
     332            2 :                 rich_location rich_locus (line_table,
     333            2 :                                           patterns[0]->get_locus ());
     334            8 :                 for (auto &pattern : items_no_rest.get_patterns ())
     335              :                   {
     336            6 :                     if (pattern == patterns[0])
     337            2 :                       continue;
     338            4 :                     rich_locus.add_range (pattern->get_locus (),
     339              :                                           SHOW_RANGE_WITH_CARET);
     340              :                   }
     341            2 :                 rust_error_at (rich_locus, ErrorCode::E0023,
     342              :                                "this pattern has %lu %s but the corresponding "
     343              :                                "tuple variant has %lu %s",
     344            2 :                                (unsigned long) patterns.size (),
     345            2 :                                patterns.size () == 1 ? "field" : "fields",
     346            2 :                                (unsigned long) variant->num_fields (),
     347            2 :                                variant->num_fields () == 1 ? "field"
     348              :                                                            : "fields");
     349            2 :               }
     350              :             // we continue on to try and setup the types as best we can for
     351              :             // type checking
     352              :           }
     353              : 
     354              :         // iterate the fields and set them up, I wish we had ZIP
     355          959 :         size_t i = 0;
     356         1993 :         for (auto &pattern : items_no_rest.get_patterns ())
     357              :           {
     358         1036 :             if (i >= variant->num_fields ())
     359              :               break;
     360              : 
     361         1034 :             TyTy::StructFieldType *field = variant->get_field_at_index (i++);
     362         1034 :             TyTy::BaseType *fty = field->get_field_type ();
     363              : 
     364              :             // setup the type on this pattern type
     365         1034 :             context->insert_type (pattern->get_mappings (), fty);
     366         1034 :             TypeCheckPattern::Resolve (*pattern, fty);
     367              :           }
     368              :       }
     369              :       break;
     370              :     }
     371              : }
     372              : 
     373              : void
     374            3 : emit_invalid_field_error (location_t loc, Rust::TyTy::VariantDef *variant,
     375              :                           const std::string &name)
     376              : {
     377            3 :   rust_error_at (loc, ErrorCode::E0026,
     378              :                  "variant %s does not have a field named %s",
     379            3 :                  variant->get_identifier ().c_str (), name.c_str ());
     380            3 : }
     381              : 
     382              : void
     383          164 : TypeCheckPattern::visit (HIR::StructPattern &pattern)
     384              : {
     385          164 :   TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
     386          164 :   if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
     387              :     {
     388            0 :       rust_error_at (pattern.get_locus (),
     389              :                      "expected tuple struct/variant, found: %s",
     390            0 :                      pattern_ty->get_name ().c_str ());
     391            3 :       return;
     392              :     }
     393              : 
     394          164 :   infered = pattern_ty;
     395          164 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
     396          164 :   if (adt->number_of_variants () == 0)
     397              :     {
     398            0 :       HIR::PathInExpression &path = pattern.get_path ();
     399            0 :       const AST::SimplePath &sp = path.as_simple_path ();
     400            0 :       rust_error_at (pattern.get_locus (), ErrorCode::E0574,
     401              :                      "expected struct, variant or union type, found enum %qs",
     402            0 :                      sp.as_string ().c_str ());
     403            0 :       return;
     404            0 :     }
     405              : 
     406          164 :   TyTy::VariantDef *variant = adt->get_variants ().at (0);
     407          164 :   if (adt->is_enum ())
     408              :     {
     409          118 :       HirId variant_id = UNKNOWN_HIRID;
     410          118 :       bool ok = context->lookup_variant_definition (
     411          118 :         pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
     412          118 :       if (!ok)
     413              :         {
     414            1 :           HIR::PathInExpression &path = pattern.get_path ();
     415            1 :           const AST::SimplePath &sp = path.as_simple_path ();
     416            1 :           rust_error_at (
     417            1 :             pattern.get_locus (), ErrorCode::E0574,
     418              :             "expected struct, variant or union type, found enum %qs",
     419            1 :             sp.as_string ().c_str ());
     420            1 :           return;
     421            1 :         }
     422              : 
     423          117 :       ok = adt->lookup_variant_by_id (variant_id, &variant);
     424          117 :       rust_assert (ok);
     425              :     }
     426              : 
     427              :   // error[E0532]: expected tuple struct or tuple variant, found struct
     428              :   // variant `Foo::D`
     429          163 :   bool error_E0532 = false;
     430          163 :   if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
     431              :     {
     432              :       // Tuple structs can still be matched with struct patterns via index
     433              :       // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
     434              :       // type TUPLE_PAT. Throw E0532 if not.
     435           16 :       auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
     436           39 :       for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
     437              :         {
     438           25 :           if (field->get_item_type ()
     439              :               != HIR::StructPatternField::ItemType::TUPLE_PAT)
     440              :             {
     441              :               error_E0532 = true;
     442              :               break;
     443              :             }
     444              :         }
     445              :     }
     446          147 :   else if (variant->get_variant_type ()
     447              :            != TyTy::VariantDef::VariantType::STRUCT)
     448              :     {
     449              :       error_E0532 = true;
     450              :     }
     451              : 
     452           16 :   if (error_E0532)
     453              :     {
     454            2 :       std::string variant_type
     455            2 :         = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
     456              : 
     457            2 :       rich_location rich_locus (line_table, pattern.get_locus ());
     458            2 :       std::string rich_msg = "use the tuple variant pattern syntax instead "
     459            4 :                              + variant->get_identifier () + "(_)";
     460            2 :       rich_locus.add_fixit_replace (rich_msg.c_str ());
     461              : 
     462            2 :       rust_error_at (rich_locus, ErrorCode::E0769,
     463              :                      "%s variant %qs written as struct variant",
     464              :                      variant_type.c_str (),
     465            2 :                      variant->get_identifier ().c_str ());
     466            2 :       return;
     467            2 :     }
     468              : 
     469          161 :   std::vector<std::string> named_fields;
     470          161 :   auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
     471          432 :   for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
     472              :     {
     473          271 :       switch (field->get_item_type ())
     474              :         {
     475           23 :         case HIR::StructPatternField::ItemType::TUPLE_PAT:
     476           23 :           {
     477           23 :             HIR::StructPatternFieldTuplePat &tuple_pat
     478           23 :               = static_cast<HIR::StructPatternFieldTuplePat &> (*field.get ());
     479              : 
     480           23 :             if ((size_t) tuple_pat.get_index () >= variant->num_fields ())
     481              :               {
     482            2 :                 emit_invalid_field_error (tuple_pat.get_locus (), variant,
     483            2 :                                           std::to_string (
     484              :                                             tuple_pat.get_index ()));
     485            2 :                 break;
     486              :               }
     487           21 :             named_fields.push_back (std::to_string (tuple_pat.get_index ()));
     488           21 :             TyTy::StructFieldType *field
     489           21 :               = variant->get_field_at_index (tuple_pat.get_index ());
     490           21 :             TyTy::BaseType *fty = field->get_field_type ();
     491           21 :             TypeCheckPattern::Resolve (tuple_pat.get_tuple_pattern (), fty);
     492              :           }
     493           21 :           break;
     494              : 
     495          150 :         case HIR::StructPatternField::ItemType::IDENT_PAT:
     496          150 :           {
     497          150 :             HIR::StructPatternFieldIdentPat &ident
     498          150 :               = static_cast<HIR::StructPatternFieldIdentPat &> (*field);
     499              : 
     500          150 :             TyTy::StructFieldType *field = nullptr;
     501          150 :             if (!variant->lookup_field (ident.get_identifier ().as_string (),
     502              :                                         &field, nullptr))
     503              :               {
     504            0 :                 emit_invalid_field_error (ident.get_locus (), variant,
     505            0 :                                           ident.get_identifier ().as_string ());
     506            0 :                 break;
     507              :               }
     508          150 :             named_fields.push_back (ident.get_identifier ().as_string ());
     509              : 
     510          150 :             TyTy::BaseType *fty = field->get_field_type ();
     511          150 :             TypeCheckPattern::Resolve (ident.get_pattern (), fty);
     512              :           }
     513          150 :           break;
     514              : 
     515           98 :         case HIR::StructPatternField::ItemType::IDENT:
     516           98 :           {
     517           98 :             HIR::StructPatternFieldIdent &ident
     518           98 :               = static_cast<HIR::StructPatternFieldIdent &> (*field);
     519              : 
     520           98 :             TyTy::StructFieldType *field = nullptr;
     521           98 :             if (!variant->lookup_field (ident.get_identifier ().as_string (),
     522              :                                         &field, nullptr))
     523              :               {
     524            1 :                 emit_invalid_field_error (ident.get_locus (), variant,
     525            1 :                                           ident.get_identifier ().as_string ());
     526            1 :                 break;
     527              :               }
     528           97 :             named_fields.push_back (ident.get_identifier ().as_string ());
     529              : 
     530              :             // setup the type on this pattern
     531           97 :             TyTy::BaseType *fty = field->get_field_type ();
     532           97 :             context->insert_type (ident.get_mappings (), fty);
     533              :           }
     534           97 :           break;
     535              :         }
     536              :     }
     537              : 
     538              :   // check the elements
     539          161 :   if (adt->is_union ())
     540              :     {
     541            5 :       auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
     542            5 :       if (struct_pattern_elems.get_struct_pattern_fields ().size () != 1)
     543            2 :         rust_error_at (pattern.get_locus (),
     544              :                        "union patterns should have exactly one field");
     545              : 
     546              :       else
     547              :         {
     548            6 :           switch (struct_pattern_elems.get_struct_pattern_fields ()
     549            3 :                     .at (0)
     550            3 :                     ->get_item_type ())
     551              :             {
     552              :             case HIR::StructPatternField::ItemType::IDENT:
     553              :             case HIR::StructPatternField::ItemType::IDENT_PAT:
     554              :               break;
     555            0 :             default:
     556            0 :               {
     557            0 :                 auto first_elem
     558            0 :                   = struct_pattern_elems.get_struct_pattern_fields ()
     559            0 :                       .at (0)
     560            0 :                       ->to_string ();
     561            0 :                 rust_error_at (pattern.get_locus (),
     562              :                                "%qs cannot be used in union patterns",
     563              :                                first_elem.c_str ());
     564            0 :               }
     565              :             }
     566              :         }
     567              :     }
     568              :   else
     569              :     {
     570              :       // Expects enum struct or struct struct.
     571              :       // error[E0027]: pattern does not mention fields `x`, `y`
     572              :       // error[E0026]: variant `Foo::D` does not have a field named `b`
     573          156 :       if (!pattern.get_struct_pattern_elems ().has_rest ()
     574          307 :           && named_fields.size () != variant->num_fields ())
     575              :         {
     576            3 :           std::map<std::string, bool> missing_names;
     577              : 
     578              :           // populate with all fields
     579            9 :           for (auto &field : variant->get_fields ())
     580            6 :             missing_names[field->get_name ()] = true;
     581              : 
     582              :           // then eliminate with named_fields
     583            4 :           for (auto &named : named_fields)
     584            1 :             missing_names.erase (named);
     585              : 
     586              :           // then get the list of missing names
     587            3 :           size_t i = 0;
     588            3 :           std::string missing_fields_str;
     589            8 :           for (auto it = missing_names.begin (); it != missing_names.end ();
     590            5 :                it++)
     591              :             {
     592            5 :               bool has_next = (i + 1) < missing_names.size ();
     593           13 :               missing_fields_str += it->first + (has_next ? ", " : "");
     594            5 :               i++;
     595              :             }
     596              : 
     597            3 :           rust_error_at (pattern.get_locus (), ErrorCode::E0027,
     598              :                          "pattern does not mention fields %s",
     599              :                          missing_fields_str.c_str ());
     600            3 :         }
     601              :     }
     602          161 : }
     603              : 
     604              : void
     605         1250 : TypeCheckPattern::visit (HIR::WildcardPattern &pattern)
     606              : {
     607              :   // wildcard patterns within the MatchArm's are simply just the same type as
     608              :   // the parent
     609         1250 :   infered = parent->clone ();
     610         1250 :   infered->set_ref (pattern.get_mappings ().get_hirid ());
     611         1250 : }
     612              : 
     613              : void
     614          424 : TypeCheckPattern::visit (HIR::TuplePattern &pattern)
     615              : {
     616          424 :   std::unique_ptr<HIR::TuplePatternItems> items;
     617              : 
     618              :   // Check whether parent is tuple
     619          424 :   auto resolved_parent = parent->destructure ();
     620          424 :   if (resolved_parent->get_kind () != TyTy::TUPLE)
     621              :     {
     622            3 :       rust_error_at (pattern.get_locus (), "expected %s, found tuple",
     623            3 :                      parent->as_string ().c_str ());
     624            3 :       return;
     625              :     }
     626          421 :   TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent);
     627              : 
     628          421 :   switch (pattern.get_items ().get_item_type ())
     629              :     {
     630          394 :     case HIR::TuplePatternItems::ItemType::NO_REST:
     631          394 :       {
     632          394 :         auto &ref
     633          394 :           = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
     634              : 
     635          394 :         const auto &patterns = ref.get_patterns ();
     636          394 :         size_t nitems_to_resolve = patterns.size ();
     637              : 
     638          394 :         if (patterns.size () != par.get_fields ().size ())
     639              :           {
     640            4 :             emit_pattern_size_error (pattern, par.get_fields ().size (),
     641              :                                      patterns.size ());
     642            4 :             nitems_to_resolve
     643            4 :               = std::min (nitems_to_resolve, par.get_fields ().size ());
     644              :           }
     645              : 
     646          394 :         std::vector<TyTy::TyVar> pattern_elems;
     647         1197 :         for (size_t i = 0; i < nitems_to_resolve; i++)
     648              :           {
     649          803 :             auto &p = patterns[i];
     650          803 :             TyTy::BaseType *par_type = par.get_field (i);
     651              : 
     652          803 :             TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
     653          803 :             pattern_elems.emplace_back (elem->get_ref ());
     654              :           }
     655          788 :         infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
     656          788 :                                        pattern.get_locus (), pattern_elems);
     657          394 :       }
     658          394 :       break;
     659              : 
     660           27 :     case HIR::TuplePatternItems::ItemType::HAS_REST:
     661           27 :       {
     662           27 :         HIR::TuplePatternItemsHasRest &ref
     663           27 :           = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
     664              : 
     665           27 :         const auto &lower = ref.get_lower_patterns ();
     666           27 :         const auto &upper = ref.get_upper_patterns ();
     667           27 :         size_t min_size_required = lower.size () + upper.size ();
     668              : 
     669              :         // Ensure that size of lower and upper patterns <= parent size
     670           27 :         if (min_size_required > par.get_fields ().size ())
     671              :           {
     672            3 :             emit_pattern_size_error (pattern, par.get_fields ().size (),
     673              :                                      min_size_required);
     674              :             // continue and attempt to resolve individual items in the pattern
     675              :           }
     676              : 
     677              :         // Resolve lower patterns
     678           27 :         std::vector<TyTy::TyVar> pattern_elems;
     679           27 :         size_t nlower_items_to_resolve
     680           27 :           = std::min (lower.size (), par.get_fields ().size ());
     681           55 :         for (size_t i = 0; i < nlower_items_to_resolve; i++)
     682              :           {
     683           28 :             auto &p = lower[i];
     684           28 :             TyTy::BaseType *par_type = par.get_field (i);
     685              : 
     686           28 :             TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
     687           28 :             pattern_elems.emplace_back (elem->get_ref ());
     688              :           }
     689              : 
     690           27 :         if (lower.size () > par.get_fields ().size ())
     691              :           break;
     692              : 
     693              :         // Pad pattern_elems until needing to resolve upper patterns
     694           27 :         size_t rest_end
     695           27 :           = std::max (par.get_fields ().size () - upper.size (), lower.size ());
     696           71 :         for (size_t i = lower.size (); i < rest_end; i++)
     697              :           {
     698           44 :             TyTy::BaseType *par_type = par.get_field (i);
     699           44 :             pattern_elems.emplace_back (par_type->get_ref ());
     700              :           }
     701              : 
     702           27 :         size_t nupper_items_to_resolve
     703           27 :           = std::min (upper.size (),
     704           27 :                       par.get_fields ().size () - pattern_elems.size ());
     705              :         // Resolve upper patterns
     706           55 :         for (size_t i = 0; i < nupper_items_to_resolve; i++)
     707              :           {
     708           28 :             auto &p = upper[i];
     709           28 :             TyTy::BaseType *par_type = par.get_field (rest_end + i);
     710              : 
     711           28 :             TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
     712           28 :             pattern_elems.emplace_back (elem->get_ref ());
     713              :           }
     714              : 
     715           54 :         infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
     716           54 :                                        pattern.get_locus (), pattern_elems);
     717            0 :       }
     718           27 :       break;
     719              :     }
     720          424 : }
     721              : 
     722              : void
     723          425 : TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
     724              : {
     725          425 :   TyTy::BaseType *resolved
     726          425 :     = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
     727          425 :                        pattern.get_locus ());
     728          425 :   if (resolved->get_kind () == TyTy::TypeKind::ERROR)
     729              :     {
     730            0 :       infered = resolved;
     731            0 :       return;
     732              :     }
     733              : 
     734          425 :   infered = unify_site (pattern.get_mappings ().get_hirid (),
     735          425 :                         TyTy::TyWithLocation (parent),
     736          425 :                         TyTy::TyWithLocation (resolved), pattern.get_locus ());
     737              : }
     738              : 
     739              : void
     740           40 : TypeCheckPattern::visit (HIR::RangePattern &pattern)
     741              : {
     742              :   // Resolve the upper and lower bounds, and ensure they are compatible types
     743           40 :   TyTy::BaseType *upper = nullptr, *lower = nullptr;
     744              : 
     745           40 :   upper = typecheck_range_pattern_bound (pattern.get_upper_bound (),
     746           40 :                                          pattern.get_mappings (),
     747           40 :                                          pattern.get_locus ());
     748              : 
     749          120 :   lower = typecheck_range_pattern_bound (pattern.get_lower_bound (),
     750           40 :                                          pattern.get_mappings (),
     751           40 :                                          pattern.get_locus ());
     752              : 
     753           40 :   infered = unify_site (pattern.get_mappings ().get_hirid (),
     754           40 :                         TyTy::TyWithLocation (upper),
     755           40 :                         TyTy::TyWithLocation (lower), pattern.get_locus ());
     756           40 : }
     757              : 
     758              : void
     759        38934 : TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
     760              : {
     761        38934 :   if (pattern.has_subpattern ())
     762              :     {
     763           17 :       TypeCheckPattern::Resolve (pattern.get_subpattern (), parent);
     764              :     }
     765              : 
     766        38934 :   if (!pattern.get_is_ref ())
     767              :     {
     768        38931 :       infered = parent;
     769        38931 :       return;
     770              :     }
     771              : 
     772            9 :   infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
     773            3 :                                      TyTy::TyVar (parent->get_ref ()),
     774            3 :                                      pattern.is_mut () ? Mutability::Mut
     775            6 :                                                        : Mutability::Imm);
     776              : }
     777              : 
     778              : void
     779            0 : TypeCheckPattern::visit (HIR::QualifiedPathInExpression &pattern)
     780              : {
     781            0 :   rust_sorry_at (pattern.get_locus (),
     782              :                  "type checking qualified path patterns not supported");
     783            0 : }
     784              : 
     785              : void
     786          199 : TypeCheckPattern::visit (HIR::ReferencePattern &pattern)
     787              : {
     788          199 :   if (parent->get_kind () != TyTy::TypeKind::REF)
     789              :     {
     790            1 :       rust_error_at (pattern.get_locus (), "expected %s, found reference",
     791            1 :                      parent->as_string ().c_str ());
     792            1 :       return;
     793              :     }
     794              : 
     795          198 :   auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
     796          198 :   TyTy::BaseType *infered_base
     797          198 :     = TypeCheckPattern::Resolve (pattern.get_referenced_pattern (),
     798              :                                  ref_ty_ty.get_base ());
     799          594 :   infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
     800          198 :                                      TyTy::TyVar (infered_base->get_ref ()),
     801          198 :                                      pattern.is_mut () ? Mutability::Mut
     802          396 :                                                        : Mutability::Imm);
     803              : }
     804              : 
     805              : void
     806           76 : TypeCheckPattern::visit (HIR::SlicePattern &pattern)
     807              : {
     808           76 :   auto resolved_parent = parent->destructure ();
     809           76 :   TyTy::BaseType *parent_element_ty = nullptr;
     810           76 :   switch (resolved_parent->get_kind ())
     811              :     {
     812           37 :     case TyTy::ARRAY:
     813           37 :       {
     814           37 :         auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
     815           37 :         parent_element_ty = array_ty_ty.get_element_type ();
     816           37 :         auto capacity = array_ty_ty.get_capacity ();
     817              : 
     818           37 :         tree cap = error_mark_node;
     819           37 :         if (capacity->get_kind () != TyTy::TypeKind::CONST)
     820              :           {
     821              :             // Error case - capacity is not a const type
     822              :             break;
     823              :           }
     824              : 
     825           37 :         auto *capacity_const = capacity->as_const_type ();
     826           37 :         switch (capacity_const->const_kind ())
     827              :           {
     828           37 :           case TyTy::BaseConstType::ConstKind::Value:
     829           37 :             {
     830           37 :               const auto &const_value
     831              :                 = *static_cast<TyTy::ConstValueType *> (capacity);
     832           37 :               cap = const_value.get_value ();
     833              :             }
     834           37 :             break;
     835              : 
     836            0 :           case TyTy::BaseConstType::ConstKind::Decl:
     837            0 :           case TyTy::BaseConstType::ConstKind::Infer:
     838            0 :           case TyTy::BaseConstType::ConstKind::Error:
     839            0 :             cap = error_mark_node;
     840            0 :             break;
     841              :           }
     842              : 
     843           37 :         if (error_operand_p (cap))
     844              :           {
     845            0 :             rust_error_at (parent->get_locus (),
     846              :                            "capacity of array %qs is not known at compile time",
     847            0 :                            array_ty_ty.get_name ().c_str ());
     848            0 :             break;
     849              :           }
     850           37 :         auto cap_wi = wi::to_wide (cap).to_uhwi ();
     851              : 
     852              :         // size check during compile time
     853           37 :         switch (pattern.get_items ().get_item_type ())
     854              :           {
     855           16 :           case HIR::SlicePatternItems::ItemType::NO_REST:
     856           16 :             {
     857           16 :               auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> (
     858           16 :                 pattern.get_items ());
     859           16 :               if (cap_wi != ref.get_patterns ().size ())
     860              :                 {
     861            2 :                   rust_error_at (
     862            1 :                     pattern.get_locus (), ErrorCode::E0527,
     863              :                     "pattern requires %lu elements but array has %lu",
     864            1 :                     (unsigned long) ref.get_patterns ().size (),
     865              :                     (unsigned long) cap_wi);
     866            1 :                   break;
     867              :                 }
     868              :             }
     869              :             break;
     870           21 :           case HIR::SlicePatternItems::ItemType::HAS_REST:
     871           21 :             {
     872           21 :               auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> (
     873           21 :                 pattern.get_items ());
     874           21 :               auto pattern_min_cap = ref.get_lower_patterns ().size ()
     875           21 :                                      + ref.get_upper_patterns ().size ();
     876              : 
     877           21 :               if (cap_wi < pattern_min_cap)
     878              :                 {
     879            0 :                   rust_error_at (pattern.get_locus (), ErrorCode::E0528,
     880              :                                  "pattern requires at least %lu elements but "
     881              :                                  "array has %lu",
     882              :                                  (unsigned long) pattern_min_cap,
     883              :                                  (unsigned long) cap_wi);
     884            0 :                   break;
     885              :                 }
     886              :             }
     887              :             break;
     888              :           }
     889              : 
     890              :         break;
     891              :       }
     892            0 :     case TyTy::SLICE:
     893            0 :       {
     894            0 :         auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent);
     895            0 :         parent_element_ty = slice_ty_ty.get_element_type ();
     896            0 :         break;
     897              :       }
     898           39 :     case TyTy::REF:
     899           39 :       {
     900           39 :         auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
     901           39 :         const TyTy::SliceType *slice = nullptr;
     902           39 :         if (!ref_ty_ty.is_dyn_slice_type (&slice))
     903              :           {
     904            0 :             rust_error_at (pattern.get_locus (), "expected %s, found slice",
     905            0 :                            parent->as_string ().c_str ());
     906            0 :             return;
     907              :           }
     908           39 :         parent_element_ty = slice->get_element_type ();
     909           39 :         break;
     910              :       }
     911            0 :     default:
     912            0 :       {
     913            0 :         rust_error_at (pattern.get_locus (), "expected %s, found slice",
     914            0 :                        parent->as_string ().c_str ());
     915            0 :         return;
     916              :       }
     917              :     }
     918              : 
     919           76 :   rust_assert (parent_element_ty != nullptr);
     920              :   // infered inherits array/slice typing from parent
     921           76 :   infered = parent->clone ();
     922           76 :   infered->set_ref (pattern.get_mappings ().get_hirid ());
     923              : 
     924              :   // Type check every item in the SlicePattern against parent's element ty
     925           76 :   switch (pattern.get_items ().get_item_type ())
     926              :     {
     927           32 :     case HIR::SlicePatternItems::ItemType::NO_REST:
     928           32 :       {
     929           32 :         auto &ref
     930           32 :           = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
     931           96 :         for (const auto &pattern_member : ref.get_patterns ())
     932              :           {
     933           64 :             TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
     934              :           }
     935              :         break;
     936              :       }
     937           44 :     case HIR::SlicePatternItems::ItemType::HAS_REST:
     938           44 :       {
     939           44 :         auto &ref
     940           44 :           = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
     941           87 :         for (const auto &pattern_member : ref.get_lower_patterns ())
     942              :           {
     943           43 :             TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
     944              :           }
     945           87 :         for (const auto &pattern_member : ref.get_upper_patterns ())
     946              :           {
     947           43 :             TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
     948              :           }
     949              :         break;
     950              :       }
     951              :     }
     952              : }
     953              : 
     954              : void
     955            7 : TypeCheckPattern::emit_pattern_size_error (const HIR::Pattern &pattern,
     956              :                                            size_t expected_field_count,
     957              :                                            size_t got_field_count)
     958              : {
     959            7 :   rich_location r (line_table, pattern.get_locus ());
     960            7 :   r.add_range (mappings.lookup_location (parent->get_ref ()));
     961           18 :   rust_error_at (r,
     962              :                  "expected a tuple with %lu %s, found one "
     963              :                  "with %lu %s",
     964              :                  (unsigned long) expected_field_count,
     965              :                  expected_field_count == 1 ? "element" : "elements",
     966              :                  (unsigned long) got_field_count,
     967              :                  got_field_count == 1 ? "element" : "elements");
     968            7 : }
     969              : 
     970              : TyTy::BaseType *
     971           80 : TypeCheckPattern::typecheck_range_pattern_bound (
     972              :   Rust::HIR::RangePatternBound &bound, Analysis::NodeMapping mappings,
     973              :   location_t locus)
     974              : {
     975           80 :   TyTy::BaseType *resolved_bound = nullptr;
     976           80 :   switch (bound.get_bound_type ())
     977              :     {
     978           59 :     case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
     979           59 :       {
     980           59 :         auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
     981              : 
     982           59 :         HIR::Literal lit = ref.get_literal ();
     983              : 
     984           59 :         resolved_bound = resolve_literal (mappings, lit, locus);
     985           59 :       }
     986           59 :       break;
     987              : 
     988           21 :     case HIR::RangePatternBound::RangePatternBoundType::PATH:
     989           21 :       {
     990           21 :         auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
     991              : 
     992           21 :         resolved_bound = TypeCheckExpr::Resolve (ref.get_path ());
     993              :       }
     994           21 :       break;
     995              : 
     996            0 :     case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
     997            0 :       {
     998            0 :         auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
     999              : 
    1000            0 :         resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ());
    1001              :       }
    1002            0 :       break;
    1003              :     }
    1004              : 
    1005           80 :   return resolved_bound;
    1006              : }
    1007              : 
    1008              : void
    1009          145 : TypeCheckPattern::visit (HIR::AltPattern &pattern)
    1010              : {
    1011          145 :   const auto &alts = pattern.get_alts ();
    1012              : 
    1013              :   // lub - taken from TypeCheckExpr::visit(ArrayExpr)
    1014          145 :   std::vector<TyTy::BaseType *> types;
    1015          436 :   for (auto &alt_pattern : alts)
    1016              :     {
    1017          291 :       types.push_back (TypeCheckPattern::Resolve (*alt_pattern, parent));
    1018              :     }
    1019              : 
    1020          145 :   TyTy::BaseType *alt_pattern_type
    1021          145 :     = TyTy::TyVar::get_implicit_infer_var (pattern.get_locus ()).get_tyty ();
    1022              : 
    1023          436 :   for (auto &type : types)
    1024              :     {
    1025          291 :       alt_pattern_type
    1026          291 :         = unify_site (pattern.get_mappings ().get_hirid (),
    1027          291 :                       TyTy::TyWithLocation (alt_pattern_type),
    1028          291 :                       TyTy::TyWithLocation (type, type->get_locus ()),
    1029          291 :                       pattern.get_locus ());
    1030              :     }
    1031              : 
    1032          145 :   infered = alt_pattern_type;
    1033          145 : }
    1034              : 
    1035              : TyTy::BaseType *
    1036            3 : ClosureParamInfer::Resolve (HIR::Pattern &pattern)
    1037              : {
    1038            3 :   ClosureParamInfer resolver;
    1039            3 :   pattern.accept_vis (resolver);
    1040              : 
    1041            3 :   if (resolver.infered->get_kind () != TyTy::TypeKind::ERROR)
    1042              :     {
    1043            3 :       resolver.context->insert_implicit_type (resolver.infered->get_ref (),
    1044              :                                               resolver.infered);
    1045            3 :       resolver.mappings.insert_location (resolver.infered->get_ref (),
    1046            3 :                                          pattern.get_locus ());
    1047              :     }
    1048            3 :   return resolver.infered;
    1049            3 : }
    1050              : 
    1051            3 : ClosureParamInfer::ClosureParamInfer ()
    1052            3 :   : TypeCheckBase (), infered (new TyTy::ErrorType (0))
    1053            3 : {}
    1054              : 
    1055              : void
    1056            1 : ClosureParamInfer::visit (HIR::WildcardPattern &pattern)
    1057              : {
    1058            1 :   HirId id = pattern.get_mappings ().get_hirid ();
    1059            1 :   infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
    1060              :                                  TyTy::InferType::TypeHint::Default (),
    1061            1 :                                  pattern.get_locus ());
    1062            1 : }
    1063              : 
    1064              : void
    1065            1 : ClosureParamInfer::visit (HIR::IdentifierPattern &pattern)
    1066              : {
    1067            1 :   if (pattern.has_subpattern ())
    1068              :     {
    1069            0 :       ClosureParamInfer::Resolve (pattern.get_subpattern ());
    1070              :     }
    1071              : 
    1072            1 :   HirId id = pattern.get_mappings ().get_hirid ();
    1073            1 :   infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
    1074              :                                  TyTy::InferType::TypeHint::Default (),
    1075            1 :                                  pattern.get_locus ());
    1076            1 : }
    1077              : 
    1078              : void
    1079            1 : ClosureParamInfer::visit (HIR::ReferencePattern &pattern)
    1080              : {
    1081            1 :   TyTy::BaseType *element
    1082            1 :     = ClosureParamInfer::Resolve (pattern.get_referenced_pattern ());
    1083              : 
    1084            1 :   HirId id = pattern.get_mappings ().get_hirid ();
    1085            1 :   infered = new TyTy::ReferenceType (id, TyTy::TyVar (element->get_ref ()),
    1086            2 :                                      pattern.get_mutability ());
    1087            1 : }
    1088              : 
    1089              : void
    1090            0 : ClosureParamInfer::visit (HIR::PathInExpression &pattern)
    1091              : {
    1092            0 :   rust_sorry_at (pattern.get_locus (),
    1093              :                  "unable to infer this kind of parameter pattern");
    1094            0 : }
    1095              : 
    1096              : void
    1097            0 : ClosureParamInfer::visit (HIR::StructPattern &pattern)
    1098              : {
    1099            0 :   rust_sorry_at (pattern.get_locus (),
    1100              :                  "unable to infer this kind of parameter pattern");
    1101            0 : }
    1102              : 
    1103              : void
    1104            0 : ClosureParamInfer::visit (HIR::TupleStructPattern &pattern)
    1105              : {
    1106            0 :   rust_sorry_at (pattern.get_locus (),
    1107              :                  "unable to infer this kind of parameter pattern");
    1108            0 : }
    1109              : 
    1110              : void
    1111            0 : ClosureParamInfer::visit (HIR::TuplePattern &pattern)
    1112              : {
    1113            0 :   rust_sorry_at (pattern.get_locus (),
    1114              :                  "unable to infer this kind of parameter pattern");
    1115            0 : }
    1116              : 
    1117              : void
    1118            0 : ClosureParamInfer::visit (HIR::LiteralPattern &pattern)
    1119              : {
    1120            0 :   rust_sorry_at (pattern.get_locus (),
    1121              :                  "unable to infer this kind of parameter pattern");
    1122            0 : }
    1123              : 
    1124              : void
    1125            0 : ClosureParamInfer::visit (HIR::RangePattern &pattern)
    1126              : {
    1127            0 :   rust_sorry_at (pattern.get_locus (),
    1128              :                  "unable to infer this kind of parameter pattern");
    1129            0 : }
    1130              : 
    1131              : void
    1132            0 : ClosureParamInfer::visit (HIR::QualifiedPathInExpression &pattern)
    1133              : {
    1134            0 :   rust_sorry_at (pattern.get_locus (),
    1135              :                  "unable to infer this kind of parameter pattern");
    1136            0 : }
    1137              : 
    1138              : void
    1139            0 : ClosureParamInfer::visit (HIR::SlicePattern &pattern)
    1140              : {
    1141            0 :   rust_sorry_at (pattern.get_locus (),
    1142              :                  "unable to infer this kind of parameter pattern");
    1143            0 : }
    1144              : 
    1145              : void
    1146            0 : ClosureParamInfer::visit (HIR::AltPattern &pattern)
    1147              : {
    1148            0 :   rust_sorry_at (pattern.get_locus (),
    1149              :                  "unable to infer this kind of parameter pattern");
    1150            0 : }
    1151              : 
    1152              : } // namespace Resolver
    1153              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.