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