LCOV - code coverage report
Current view: top level - gcc/rust/checks/errors - rust-hir-pattern-analysis.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 73.5 % 912 670
Test Date: 2026-10-03 16:17:38 Functions: 58.7 % 155 91
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-rib.h"
      20              : #include "rust-system.h"
      21              : #include "rust-hir-pattern-analysis.h"
      22              : #include "rust-diagnostics.h"
      23              : #include "rust-hir-full-decls.h"
      24              : #include "rust-hir-path.h"
      25              : #include "rust-hir-pattern.h"
      26              : #include "rust-hir.h"
      27              : #include "rust-mapping-common.h"
      28              : #include "rust-system.h"
      29              : #include "rust-tyty.h"
      30              : #include "rust-finalized-name-resolution-context.h"
      31              : 
      32              : namespace Rust {
      33              : namespace Analysis {
      34              : 
      35         4501 : PatternChecker::PatternChecker ()
      36         4501 :   : tyctx (*Resolver::TypeCheckContext::get ()),
      37         4501 :     resolver (Resolver2_0::FinalizedNameResolutionContext::get ()),
      38         9002 :     mappings (Analysis::Mappings::get ())
      39         4501 : {}
      40              : 
      41              : void
      42         4501 : PatternChecker::go (HIR::Crate &crate)
      43              : {
      44         4501 :   rust_debug ("started pattern check");
      45        23663 :   for (auto &item : crate.get_items ())
      46        19167 :     item->accept_vis (*this);
      47         4496 :   rust_debug ("finished pattern check");
      48         4496 : }
      49              : 
      50              : void
      51            0 : PatternChecker::visit (Lifetime &)
      52            0 : {}
      53              : 
      54              : void
      55            0 : PatternChecker::visit (LifetimeParam &)
      56            0 : {}
      57              : 
      58              : void
      59        37103 : PatternChecker::visit (PathInExpression &path)
      60        37103 : {}
      61              : 
      62              : void
      63            0 : PatternChecker::visit (TypePathSegment &)
      64            0 : {}
      65              : 
      66              : void
      67            0 : PatternChecker::visit (TypePathSegmentGeneric &)
      68            0 : {}
      69              : 
      70              : void
      71            0 : PatternChecker::visit (TypePathSegmentFunction &)
      72            0 : {}
      73              : 
      74              : void
      75            0 : PatternChecker::visit (TypePath &)
      76            0 : {}
      77              : 
      78              : void
      79           15 : PatternChecker::visit (QualifiedPathInExpression &)
      80           15 : {}
      81              : 
      82              : void
      83            0 : PatternChecker::visit (QualifiedPathInType &)
      84            0 : {}
      85              : 
      86              : void
      87        20089 : PatternChecker::visit (LiteralExpr &)
      88        20089 : {}
      89              : 
      90              : void
      91         2131 : PatternChecker::visit (BorrowExpr &expr)
      92              : {
      93         2131 :   expr.get_expr ().accept_vis (*this);
      94         2131 : }
      95              : 
      96              : void
      97         4275 : PatternChecker::visit (DereferenceExpr &expr)
      98              : {
      99         4275 :   expr.get_expr ().accept_vis (*this);
     100         4275 : }
     101              : 
     102              : void
     103            0 : PatternChecker::visit (ErrorPropagationExpr &expr)
     104              : {
     105            0 :   expr.get_expr ().accept_vis (*this);
     106            0 : }
     107              : 
     108              : void
     109          603 : PatternChecker::visit (NegationExpr &expr)
     110              : {
     111          603 :   expr.get_expr ().accept_vis (*this);
     112          603 : }
     113              : 
     114              : void
     115         3565 : PatternChecker::visit (ArithmeticOrLogicalExpr &expr)
     116              : {
     117         3565 :   expr.get_lhs ().accept_vis (*this);
     118         3565 :   expr.get_rhs ().accept_vis (*this);
     119         3565 : }
     120              : 
     121              : void
     122         3733 : PatternChecker::visit (ComparisonExpr &expr)
     123              : {
     124         3733 :   expr.get_lhs ().accept_vis (*this);
     125         3733 :   expr.get_rhs ().accept_vis (*this);
     126         3733 : }
     127              : 
     128              : void
     129          424 : PatternChecker::visit (LazyBooleanExpr &expr)
     130              : {
     131          424 :   expr.get_lhs ().accept_vis (*this);
     132          424 :   expr.get_rhs ().accept_vis (*this);
     133          424 : }
     134              : 
     135              : void
     136         5662 : PatternChecker::visit (TypeCastExpr &expr)
     137              : {
     138         5662 :   expr.get_expr ().accept_vis (*this);
     139         5662 : }
     140              : 
     141              : void
     142         2520 : PatternChecker::visit (AssignmentExpr &expr)
     143              : {
     144         2520 :   expr.get_lhs ().accept_vis (*this);
     145         2520 :   expr.get_rhs ().accept_vis (*this);
     146         2520 : }
     147              : 
     148              : void
     149          704 : PatternChecker::visit (CompoundAssignmentExpr &expr)
     150              : {
     151          704 :   expr.get_lhs ().accept_vis (*this);
     152          704 :   expr.get_rhs ().accept_vis (*this);
     153          704 : }
     154              : 
     155              : void
     156          340 : PatternChecker::visit (GroupedExpr &expr)
     157              : {
     158          340 :   expr.get_expr_in_parens ().accept_vis (*this);
     159          340 : }
     160              : 
     161              : void
     162          298 : PatternChecker::visit (ArrayElemsValues &elems)
     163              : {
     164         1793 :   for (auto &elem : elems.get_values ())
     165         1495 :     elem->accept_vis (*this);
     166          298 : }
     167              : 
     168              : void
     169          115 : PatternChecker::visit (ArrayElemsCopied &elems)
     170              : {
     171          115 :   elems.get_elem_to_copy ().accept_vis (*this);
     172          115 : }
     173              : 
     174              : void
     175          413 : PatternChecker::visit (ArrayExpr &expr)
     176              : {
     177          413 :   expr.get_internal_elements ().accept_vis (*this);
     178          413 : }
     179              : 
     180              : void
     181          293 : PatternChecker::visit (ArrayIndexExpr &expr)
     182              : {
     183          293 :   expr.get_array_expr ().accept_vis (*this);
     184          293 :   expr.get_index_expr ().accept_vis (*this);
     185          293 : }
     186              : 
     187              : void
     188          600 : PatternChecker::visit (TupleExpr &expr)
     189              : {
     190         1655 :   for (auto &elem : expr.get_tuple_elems ())
     191         1055 :     elem->accept_vis (*this);
     192          600 : }
     193              : 
     194              : void
     195          898 : PatternChecker::visit (TupleIndexExpr &expr)
     196              : {
     197          898 :   expr.get_tuple_expr ().accept_vis (*this);
     198          898 : }
     199              : 
     200              : void
     201           79 : PatternChecker::visit (StructExprStruct &)
     202           79 : {}
     203              : 
     204              : void
     205          235 : PatternChecker::visit (StructExprFieldIdentifier &)
     206          235 : {}
     207              : 
     208              : void
     209         2727 : PatternChecker::visit (StructExprFieldIdentifierValue &field)
     210              : {
     211         2727 :   field.get_value ().accept_vis (*this);
     212         2727 : }
     213              : 
     214              : void
     215           42 : PatternChecker::visit (StructExprFieldIndexValue &field)
     216              : {
     217           42 :   field.get_value ().accept_vis (*this);
     218           42 : }
     219              : 
     220              : void
     221         1406 : PatternChecker::visit (StructExprStructFields &expr)
     222              : {
     223         4410 :   for (auto &field : expr.get_fields ())
     224         3004 :     field->accept_vis (*this);
     225         1406 : }
     226              : 
     227              : void
     228            0 : PatternChecker::visit (StructExprStructBase &)
     229            0 : {}
     230              : 
     231              : void
     232        13059 : PatternChecker::visit (CallExpr &expr)
     233              : {
     234        13059 :   if (!expr.has_fnexpr ())
     235              :     return;
     236              : 
     237        13059 :   NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid ();
     238        13059 :   NodeId ref_node_id;
     239        13059 :   if (auto id = resolver.lookup (ast_node_id, Resolver2_0::Namespace::Values))
     240        12989 :     ref_node_id = *id;
     241              :   else
     242           70 :     return;
     243              : 
     244        12989 :   if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id))
     245              :     {
     246        12989 :       if (expr.has_params ())
     247        25451 :         for (auto &arg : expr.get_arguments ())
     248        15005 :           arg->accept_vis (*this);
     249              :     }
     250              :   else
     251              :     {
     252            0 :       rust_unreachable ();
     253              :     }
     254              : }
     255              : 
     256              : void
     257         3138 : PatternChecker::visit (MethodCallExpr &expr)
     258              : {
     259         3138 :   expr.get_receiver ().accept_vis (*this);
     260              : 
     261         5283 :   for (auto &arg : expr.get_arguments ())
     262         2145 :     arg->accept_vis (*this);
     263         3138 : }
     264              : 
     265              : void
     266         5702 : PatternChecker::visit (FieldAccessExpr &expr)
     267              : {
     268         5702 :   expr.get_receiver_expr ().accept_vis (*this);
     269         5702 : }
     270              : 
     271              : void
     272           53 : PatternChecker::visit (ClosureExpr &expr)
     273              : {
     274           53 :   expr.get_expr ().accept_vis (*this);
     275           53 : }
     276              : 
     277              : void
     278        24850 : PatternChecker::visit (BlockExpr &expr)
     279              : {
     280        49827 :   for (auto &stmt : expr.get_statements ())
     281        24977 :     stmt->accept_vis (*this);
     282              : 
     283        24850 :   if (expr.has_expr ())
     284        17959 :     expr.get_final_expr ().accept_vis (*this);
     285        24850 : }
     286              : 
     287              : void
     288           15 : PatternChecker::visit (AnonConst &expr)
     289              : {
     290           15 :   expr.get_inner_expr ().accept_vis (*this);
     291           15 : }
     292              : 
     293              : void
     294           15 : PatternChecker::visit (ConstBlock &expr)
     295              : {
     296           15 :   expr.get_const_expr ().accept_vis (*this);
     297           15 : }
     298              : 
     299              : void
     300           25 : PatternChecker::visit (ContinueExpr &)
     301           25 : {}
     302              : 
     303              : void
     304          112 : PatternChecker::visit (BreakExpr &expr)
     305              : {
     306          112 :   if (expr.has_break_expr ())
     307           21 :     expr.get_expr ().accept_vis (*this);
     308          112 : }
     309              : 
     310              : void
     311           74 : PatternChecker::visit (RangeFromToExpr &expr)
     312              : {
     313           74 :   expr.get_from_expr ().accept_vis (*this);
     314           74 :   expr.get_to_expr ().accept_vis (*this);
     315           74 : }
     316              : 
     317              : void
     318            7 : PatternChecker::visit (RangeFromExpr &expr)
     319              : {
     320            7 :   expr.get_from_expr ().accept_vis (*this);
     321            7 : }
     322              : 
     323              : void
     324            7 : PatternChecker::visit (RangeToExpr &expr)
     325              : {
     326            7 :   expr.get_to_expr ().accept_vis (*this);
     327            7 : }
     328              : 
     329              : void
     330            0 : PatternChecker::visit (RangeFullExpr &)
     331            0 : {}
     332              : 
     333              : void
     334            0 : PatternChecker::visit (RangeToInclExpr &expr)
     335              : {
     336            0 :   expr.get_to_expr ().accept_vis (*this);
     337            0 : }
     338              : 
     339              : void
     340            4 : PatternChecker::visit (BoxExpr &expr)
     341              : {
     342            4 :   expr.get_expr ().accept_vis (*this);
     343            4 : }
     344              : 
     345              : void
     346          560 : PatternChecker::visit (ReturnExpr &expr)
     347              : {
     348          560 :   if (expr.has_return_expr ())
     349          524 :     expr.get_expr ().accept_vis (*this);
     350          560 : }
     351              : 
     352              : void
     353         3991 : PatternChecker::visit (UnsafeBlockExpr &expr)
     354              : {
     355         3991 :   expr.get_block_expr ().accept_vis (*this);
     356         3991 : }
     357              : 
     358              : void
     359          151 : PatternChecker::visit (LoopExpr &expr)
     360              : {
     361          151 :   expr.get_loop_block ().accept_vis (*this);
     362          151 : }
     363              : 
     364              : void
     365           88 : PatternChecker::visit (WhileLoopExpr &expr)
     366              : {
     367           88 :   expr.get_predicate_expr ().accept_vis (*this);
     368           88 :   expr.get_loop_block ().accept_vis (*this);
     369           88 : }
     370              : 
     371              : void
     372            0 : PatternChecker::visit (WhileLetLoopExpr &expr)
     373              : {
     374            0 :   expr.get_cond ().accept_vis (*this);
     375            0 :   expr.get_loop_block ().accept_vis (*this);
     376            0 : }
     377              : 
     378              : void
     379         1280 : PatternChecker::visit (IfExpr &expr)
     380              : {
     381         1280 :   expr.get_if_condition ().accept_vis (*this);
     382         1280 :   expr.get_if_block ().accept_vis (*this);
     383         1280 : }
     384              : 
     385              : void
     386         1335 : PatternChecker::visit (IfExprConseqElse &expr)
     387              : {
     388         1335 :   expr.get_if_condition ().accept_vis (*this);
     389         1335 :   expr.get_if_block ().accept_vis (*this);
     390         1335 :   expr.get_else_block ().accept_vis (*this);
     391         1335 : }
     392              : 
     393              : void
     394         1120 : PatternChecker::visit (MatchExpr &expr)
     395              : {
     396         1120 :   expr.get_scrutinee_expr ().accept_vis (*this);
     397              : 
     398         3680 :   for (auto &match_arm : expr.get_match_cases ())
     399         2560 :     match_arm.get_expr ().accept_vis (*this);
     400              : 
     401              :   // match expressions are only an entrypoint
     402         1120 :   TyTy::BaseType *scrutinee_ty;
     403         1120 :   bool ok = tyctx.lookup_type (
     404         1120 :     expr.get_scrutinee_expr ().get_mappings ().get_hirid (), &scrutinee_ty);
     405         1120 :   rust_assert (ok);
     406              : 
     407         1120 :   check_match_usefulness (&tyctx, scrutinee_ty, expr);
     408         1120 : }
     409              : 
     410              : void
     411            0 : PatternChecker::visit (AwaitExpr &)
     412              : {
     413              :   // TODO: Visit expression
     414            0 : }
     415              : 
     416              : void
     417            0 : PatternChecker::visit (AsyncBlockExpr &)
     418              : {
     419              :   // TODO: Visit block expression
     420            0 : }
     421              : 
     422              : void
     423           27 : PatternChecker::visit (InlineAsm &expr)
     424           27 : {}
     425              : 
     426              : void
     427            2 : PatternChecker::visit (LlvmInlineAsm &expr)
     428            2 : {}
     429              : 
     430              : void
     431           15 : PatternChecker::visit (OffsetOf &expr)
     432           15 : {}
     433              : 
     434              : void
     435            0 : PatternChecker::visit (TypeParam &)
     436            0 : {}
     437              : 
     438              : void
     439            0 : PatternChecker::visit (ConstGenericParam &)
     440            0 : {}
     441              : 
     442              : void
     443            0 : PatternChecker::visit (LifetimeWhereClauseItem &)
     444            0 : {}
     445              : 
     446              : void
     447            0 : PatternChecker::visit (TypeBoundWhereClauseItem &)
     448            0 : {}
     449              : 
     450              : void
     451         1245 : PatternChecker::visit (Module &module)
     452              : {
     453         5418 :   for (auto &item : module.get_items ())
     454         4173 :     item->accept_vis (*this);
     455         1245 : }
     456              : 
     457              : void
     458            0 : PatternChecker::visit (ExternCrate &)
     459            0 : {}
     460              : 
     461              : void
     462            0 : PatternChecker::visit (UseTreeGlob &)
     463            0 : {}
     464              : 
     465              : void
     466            0 : PatternChecker::visit (UseTreeList &)
     467            0 : {}
     468              : 
     469              : void
     470            0 : PatternChecker::visit (UseTreeRebind &)
     471            0 : {}
     472              : 
     473              : void
     474            0 : PatternChecker::visit (UseDeclaration &)
     475            0 : {}
     476              : 
     477              : void
     478        14539 : PatternChecker::visit (Function &function)
     479              : {
     480        21751 :   for (auto &param : function.get_function_params ())
     481              :     {
     482         7217 :       TyTy::BaseType *param_ty;
     483         7217 :       bool ok
     484         7217 :         = tyctx.lookup_type (param.get_mappings ().get_hirid (), &param_ty);
     485         7217 :       rust_assert (ok);
     486              : 
     487         7217 :       if (param.get_param_name ().is_refutable (*param_ty))
     488           10 :         rust_error_at (param.get_locus (), ErrorCode::E0005,
     489              :                        "refutable pattern in function parameter");
     490              :     }
     491        14534 :   function.get_definition ().accept_vis (*this);
     492        14534 : }
     493              : 
     494              : void
     495         1468 : PatternChecker::visit (TypeAlias &)
     496         1468 : {}
     497              : 
     498              : void
     499         1611 : PatternChecker::visit (StructStruct &)
     500         1611 : {}
     501              : 
     502              : void
     503          973 : PatternChecker::visit (TupleStruct &)
     504          973 : {}
     505              : 
     506              : void
     507            0 : PatternChecker::visit (EnumItem &)
     508            0 : {}
     509              : 
     510              : void
     511            0 : PatternChecker::visit (EnumItemTuple &)
     512            0 : {}
     513              : 
     514              : void
     515            0 : PatternChecker::visit (EnumItemStruct &)
     516            0 : {}
     517              : 
     518              : void
     519            0 : PatternChecker::visit (EnumItemDiscriminant &)
     520            0 : {}
     521              : 
     522              : void
     523          529 : PatternChecker::visit (Enum &)
     524          529 : {}
     525              : 
     526              : void
     527          102 : PatternChecker::visit (Union &)
     528          102 : {}
     529              : 
     530              : void
     531          529 : PatternChecker::visit (ConstantItem &const_item)
     532              : {
     533          529 :   const_item.get_expr ().accept_vis (*this);
     534          529 : }
     535              : 
     536              : void
     537           56 : PatternChecker::visit (StaticItem &static_item)
     538              : {
     539           56 :   static_item.get_expr ().accept_vis (*this);
     540           56 : }
     541              : 
     542              : void
     543         2683 : PatternChecker::visit (TraitItemFunc &item)
     544              : {
     545         2683 :   if (item.has_definition ())
     546          861 :     item.get_block_expr ().accept_vis (*this);
     547         2683 : }
     548              : 
     549              : void
     550           32 : PatternChecker::visit (TraitItemConst &item)
     551              : {
     552           32 :   if (item.has_expr ())
     553            7 :     item.get_expr ().accept_vis (*this);
     554           32 : }
     555              : 
     556              : void
     557          786 : PatternChecker::visit (TraitItemType &)
     558          786 : {}
     559              : 
     560              : void
     561         4001 : PatternChecker::visit (Trait &trait)
     562              : {
     563         7502 :   for (auto &item : trait.get_trait_items ())
     564         3501 :     item->accept_vis (*this);
     565         4001 : }
     566              : 
     567              : void
     568         6321 : PatternChecker::visit (ImplBlock &impl)
     569              : {
     570        15647 :   for (auto &item : impl.get_impl_items ())
     571         9326 :     item->accept_vis (*this);
     572         6321 : }
     573              : 
     574              : void
     575            1 : PatternChecker::visit (ExternalStaticItem &)
     576            1 : {}
     577              : 
     578              : void
     579         2668 : PatternChecker::visit (ExternalFunctionItem &)
     580         2668 : {}
     581              : 
     582              : void
     583            2 : PatternChecker::visit (ExternalTypeItem &)
     584            2 : {}
     585              : 
     586              : void
     587         1701 : PatternChecker::visit (ExternBlock &block)
     588              : {
     589              :   // FIXME: Do we need to do this?
     590         4372 :   for (auto &item : block.get_extern_items ())
     591         2671 :     item->accept_vis (*this);
     592         1701 : }
     593              : 
     594              : void
     595            0 : PatternChecker::visit (LiteralPattern &)
     596            0 : {}
     597              : 
     598              : void
     599            0 : PatternChecker::visit (IdentifierPattern &)
     600            0 : {}
     601              : 
     602              : void
     603            0 : PatternChecker::visit (WildcardPattern &)
     604            0 : {}
     605              : 
     606              : void
     607            0 : PatternChecker::visit (RangePatternBoundLiteral &)
     608            0 : {}
     609              : 
     610              : void
     611            0 : PatternChecker::visit (RangePatternBoundPath &)
     612            0 : {}
     613              : 
     614              : void
     615            0 : PatternChecker::visit (RangePatternBoundQualPath &)
     616            0 : {}
     617              : 
     618              : void
     619            0 : PatternChecker::visit (RangePattern &)
     620            0 : {}
     621              : 
     622              : void
     623            0 : PatternChecker::visit (ReferencePattern &)
     624            0 : {}
     625              : 
     626              : void
     627            0 : PatternChecker::visit (StructPatternFieldTuplePat &)
     628            0 : {}
     629              : 
     630              : void
     631            0 : PatternChecker::visit (StructPatternFieldIdentPat &)
     632            0 : {}
     633              : 
     634              : void
     635            0 : PatternChecker::visit (StructPatternFieldIdent &)
     636            0 : {}
     637              : 
     638              : void
     639            0 : PatternChecker::visit (StructPattern &)
     640            0 : {}
     641              : 
     642              : void
     643            0 : PatternChecker::visit (TupleStructItemsNoRest &)
     644            0 : {}
     645              : 
     646              : void
     647            0 : PatternChecker::visit (TupleStructItemsHasRest &)
     648            0 : {}
     649              : 
     650              : void
     651            0 : PatternChecker::visit (TupleStructPattern &)
     652            0 : {}
     653              : 
     654              : void
     655            0 : PatternChecker::visit (TuplePatternItemsNoRest &)
     656            0 : {}
     657              : 
     658              : void
     659            0 : PatternChecker::visit (TuplePatternItemsHasRest &)
     660            0 : {}
     661              : 
     662              : void
     663            0 : PatternChecker::visit (TuplePattern &)
     664            0 : {}
     665              : 
     666              : void
     667            0 : PatternChecker::visit (SlicePatternItemsNoRest &)
     668            0 : {}
     669              : 
     670              : void
     671            0 : PatternChecker::visit (SlicePatternItemsHasRest &)
     672            0 : {}
     673              : 
     674              : void
     675            0 : PatternChecker::visit (SlicePattern &)
     676            0 : {}
     677              : 
     678              : void
     679            0 : PatternChecker::visit (AltPattern &)
     680            0 : {}
     681              : 
     682              : void
     683           45 : PatternChecker::visit (EmptyStmt &)
     684           45 : {}
     685              : 
     686              : void
     687        13308 : PatternChecker::visit (LetStmt &stmt)
     688              : {
     689        13308 :   if (stmt.has_init_expr ())
     690        12154 :     stmt.get_init_expr ().accept_vis (*this);
     691              : 
     692              :   // skip let-else (allows refutable patterns)
     693        13308 :   if (stmt.has_else_expr ())
     694            5 :     return;
     695              : 
     696        13303 :   TyTy::BaseType *binding_ty;
     697        13303 :   bool ok = tyctx.lookup_type (stmt.get_pattern ().get_mappings ().get_hirid (),
     698              :                                &binding_ty);
     699        13303 :   if (!ok)
     700              :     return; // type-check failed earlier
     701              : 
     702        13303 :   if (stmt.get_pattern ().is_refutable (*binding_ty))
     703           11 :     rust_error_at (stmt.get_pattern ().get_locus (), ErrorCode::E0005,
     704              :                    "refutable pattern in local binding");
     705              : }
     706              : 
     707              : void
     708        11215 : PatternChecker::visit (ExprStmt &stmt)
     709              : {
     710        11215 :   stmt.get_expr ().accept_vis (*this);
     711        11215 : }
     712              : 
     713              : void
     714            0 : PatternChecker::visit (TraitBound &)
     715            0 : {}
     716              : 
     717              : void
     718            0 : PatternChecker::visit (ImplTraitType &)
     719            0 : {}
     720              : 
     721              : void
     722            0 : PatternChecker::visit (TraitObjectType &)
     723            0 : {}
     724              : 
     725              : void
     726            0 : PatternChecker::visit (ParenthesisedType &)
     727            0 : {}
     728              : 
     729              : void
     730            0 : PatternChecker::visit (TupleType &)
     731            0 : {}
     732              : 
     733              : void
     734            0 : PatternChecker::visit (NeverType &)
     735            0 : {}
     736              : 
     737              : void
     738            0 : PatternChecker::visit (RawPointerType &)
     739            0 : {}
     740              : 
     741              : void
     742            0 : PatternChecker::visit (ReferenceType &)
     743            0 : {}
     744              : 
     745              : void
     746            0 : PatternChecker::visit (ArrayType &)
     747            0 : {}
     748              : 
     749              : void
     750            0 : PatternChecker::visit (SliceType &)
     751            0 : {}
     752              : 
     753              : void
     754            0 : PatternChecker::visit (InferredType &)
     755            0 : {}
     756              : 
     757              : void
     758            0 : PatternChecker::visit (BareFunctionType &)
     759            0 : {}
     760              : 
     761              : bool
     762        16291 : Constructor::is_covered_by (const Constructor &o) const
     763              : {
     764        16291 :   if (o.kind == ConstructorKind::WILDCARD)
     765              :     return true;
     766              : 
     767         3817 :   switch (kind)
     768              :     {
     769         3565 :     case ConstructorKind::VARIANT:
     770         3565 :       {
     771         3565 :         rust_assert (kind == ConstructorKind::VARIANT);
     772         3565 :         return variant_idx == o.variant_idx;
     773              :       }
     774            0 :       break;
     775            0 :     case ConstructorKind::INT_RANGE:
     776            0 :       {
     777            0 :         rust_assert (kind == ConstructorKind::INT_RANGE);
     778            0 :         return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi;
     779              :       }
     780              :       break;
     781              :     case ConstructorKind::WILDCARD:
     782              :       {
     783              :         // TODO: wildcard is covered by a variant of enum with a single
     784              :         // variant
     785              :         return false;
     786              :       }
     787              :       break;
     788              :     case ConstructorKind::STRUCT:
     789              :       {
     790              :         // Struct pattern is always covered by a other struct constructor.
     791              :         return true;
     792              :       }
     793            0 :       break;
     794              :       // TODO: support references
     795            0 :     case ConstructorKind::REFERENCE:
     796            0 :     default:
     797            0 :       rust_unreachable ();
     798              :     }
     799              : }
     800              : 
     801              : bool
     802         3048 : Constructor::operator< (const Constructor &o) const
     803              : {
     804         3048 :   if (kind != o.kind)
     805            0 :     return kind < o.kind;
     806              : 
     807         3048 :   switch (kind)
     808              :     {
     809         2958 :     case ConstructorKind::VARIANT:
     810         2958 :       return variant_idx < o.variant_idx;
     811            0 :     case ConstructorKind::INT_RANGE:
     812            0 :       return int_range.lo < o.int_range.lo
     813            0 :              || (int_range.lo == o.int_range.lo
     814            0 :                  && int_range.hi < o.int_range.hi);
     815              :     case ConstructorKind::STRUCT:
     816              :     case ConstructorKind::WILDCARD:
     817              :     case ConstructorKind::REFERENCE:
     818              :       return false;
     819            0 :     default:
     820            0 :       rust_unreachable ();
     821              :     }
     822              : }
     823              : 
     824              : std::string
     825         1854 : Constructor::to_string () const
     826              : {
     827         1854 :   switch (kind)
     828              :     {
     829            0 :     case ConstructorKind::STRUCT:
     830            0 :       return "STRUCT";
     831           15 :     case ConstructorKind::VARIANT:
     832           30 :       return "VARIANT(" + std::to_string (variant_idx) + ")";
     833            0 :     case ConstructorKind::INT_RANGE:
     834            0 :       return "RANGE" + std::to_string (int_range.lo) + ".."
     835            0 :              + std::to_string (int_range.hi);
     836         1839 :     case ConstructorKind::WILDCARD:
     837         1839 :       return "_";
     838            0 :     case ConstructorKind::REFERENCE:
     839            0 :       return "REF";
     840            0 :     default:
     841            0 :       rust_unreachable ();
     842              :     }
     843              : }
     844              : 
     845              : std::vector<DeconstructedPat>
     846         5109 : DeconstructedPat::specialize (const Constructor &other_ctor,
     847              :                               int other_ctor_arity) const
     848              : {
     849         5109 :   rust_assert (other_ctor.is_covered_by (ctor));
     850         5109 :   if (ctor.is_wildcard ())
     851         4158 :     return std::vector<DeconstructedPat> (
     852              :       other_ctor_arity,
     853         4158 :       DeconstructedPat (Constructor::make_wildcard (), locus));
     854              : 
     855          951 :   return fields;
     856              : }
     857              : 
     858              : std::string
     859         1854 : DeconstructedPat::to_string () const
     860              : {
     861         3708 :   std::string s = ctor.to_string () + "[";
     862         1855 :   for (auto &f : fields)
     863            3 :     s += f.to_string () + ", ";
     864              : 
     865         5562 :   s += "](arity=" + std::to_string (arity) + ")";
     866         1854 :   return s;
     867              : }
     868              : 
     869              : bool
     870            0 : PatOrWild::is_covered_by (const Constructor &c) const
     871              : {
     872            0 :   if (pat.has_value ())
     873            0 :     return pat.value ().get_ctor ().is_covered_by (c);
     874              :   else
     875              :     return true;
     876              : }
     877              : 
     878              : std::vector<PatOrWild>
     879         5109 : PatOrWild::specialize (const Constructor &other_ctor,
     880              :                        int other_ctor_arity) const
     881              : {
     882         5109 :   if (pat.has_value ())
     883              :     {
     884         5109 :       auto v = pat.value ().specialize (other_ctor, other_ctor_arity);
     885         5109 :       std::vector<PatOrWild> ret;
     886         6962 :       for (auto &pat : v)
     887         3706 :         ret.push_back (PatOrWild::make_pattern (pat));
     888              : 
     889         5109 :       return ret;
     890         5109 :     }
     891              :   else
     892              :     {
     893            0 :       return std::vector<PatOrWild> (other_ctor_arity,
     894            0 :                                      PatOrWild::make_wildcard ());
     895              :     }
     896              : }
     897              : 
     898              : std::string
     899         1853 : PatOrWild::to_string () const
     900              : {
     901         1853 :   if (pat.has_value ())
     902         1853 :     return pat.value ().to_string ();
     903              :   else
     904            0 :     return "Wild";
     905              : }
     906              : 
     907              : void
     908         5109 : PatStack::pop_head_constructor (const Constructor &other_ctor,
     909              :                                 int other_ctor_arity)
     910              : {
     911         5109 :   rust_assert (!pats.empty ());
     912         5109 :   rust_assert (other_ctor.is_covered_by (head ().ctor ()));
     913              : 
     914         5109 :   PatOrWild &hd = head ();
     915         5109 :   auto v = hd.specialize (other_ctor, other_ctor_arity);
     916         5109 :   {
     917         5109 :     std::string s = "[";
     918         6962 :     for (auto &pat : v)
     919         5559 :       s += pat.to_string () + ", ";
     920         5109 :     s += "]";
     921              : 
     922         5109 :     rust_debug ("specialize %s with %s to %s", hd.to_string ().c_str (),
     923              :                 other_ctor.to_string ().c_str (), s.c_str ());
     924         5109 :   }
     925         5109 :   pop_head ();
     926         6962 :   for (auto &pat : v)
     927         1853 :     pats.push_back (pat);
     928         5109 : }
     929              : 
     930              : std::string
     931            0 : MatrixRow::to_string () const
     932              : {
     933            0 :   std::string s;
     934            0 :   for (const PatOrWild &pat : pats.get_subpatterns ())
     935            0 :     s += pat.to_string () + ", ";
     936            0 :   return s;
     937              : }
     938              : 
     939              : std::vector<PlaceInfo>
     940         2702 : PlaceInfo::specialize (const Constructor &c) const
     941              : {
     942         2702 :   switch (c.get_kind ())
     943              :     {
     944         1295 :     case Constructor::ConstructorKind::WILDCARD:
     945         1295 :     case Constructor::ConstructorKind::INT_RANGE:
     946         1295 :       {
     947         1295 :         return {};
     948              :       }
     949         1407 :       break;
     950         1407 :     case Constructor::ConstructorKind::STRUCT:
     951         1407 :     case Constructor::ConstructorKind::VARIANT:
     952         1407 :       {
     953         1407 :         rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
     954         1407 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
     955         1407 :         switch (adt->get_adt_kind ())
     956              :           {
     957         1407 :           case TyTy::ADTType::ADTKind::ENUM:
     958         1407 :           case TyTy::ADTType::ADTKind::STRUCT_STRUCT:
     959         1407 :           case TyTy::ADTType::ADTKind::TUPLE_STRUCT:
     960         1407 :             {
     961         1407 :               TyTy::VariantDef *variant
     962         1407 :                 = adt->get_variants ().at (c.get_variant_index ());
     963         1407 :               if (variant->get_variant_type ()
     964              :                     == TyTy::VariantDef::VariantType::NUM
     965         1407 :                   || variant->get_variant_type ()
     966              :                        == TyTy::VariantDef::VariantType::UNIT)
     967          595 :                 return {};
     968              : 
     969          812 :               std::vector<PlaceInfo> new_place_infos;
     970         1689 :               for (auto &field : variant->get_fields ())
     971          877 :                 new_place_infos.push_back (field->get_field_type ());
     972              : 
     973          812 :               return new_place_infos;
     974          812 :             }
     975            0 :             break;
     976            0 :           case TyTy::ADTType::ADTKind::UNION:
     977            0 :             {
     978              :               // TODO: support unions
     979            0 :               rust_unreachable ();
     980              :             }
     981            0 :           case TyTy::ADTType::ADTKind::EXTERN:
     982            0 :             return {};
     983              :           }
     984              :       }
     985            0 :       break;
     986            0 :     default:
     987            0 :       {
     988            0 :         rust_unreachable ();
     989              :       }
     990            0 :       break;
     991              :     }
     992              : 
     993            0 :   rust_unreachable ();
     994              : }
     995              : 
     996              : Matrix
     997         2702 : Matrix::specialize (const Constructor &ctor) const
     998              : {
     999         2702 :   auto subfields_place_info = place_infos.at (0).specialize (ctor);
    1000              : 
    1001         2702 :   std::vector<MatrixRow> new_rows;
    1002         8775 :   for (const MatrixRow &row : rows)
    1003              :     {
    1004         6073 :       PatStack pats = row.get_pats_clone ();
    1005         6073 :       const PatOrWild &hd = pats.head ();
    1006         6073 :       if (ctor.is_covered_by (hd.ctor ()))
    1007              :         {
    1008         5109 :           pats.pop_head_constructor (ctor, subfields_place_info.size ());
    1009         5109 :           new_rows.emplace_back (pats, row.is_under_guard ());
    1010              :         }
    1011         6073 :     }
    1012              : 
    1013         2702 :   if (place_infos.empty ())
    1014            0 :     return Matrix (new_rows, {});
    1015              : 
    1016              :   // push subfields of the first fields after specialization
    1017         2702 :   std::vector<PlaceInfo> new_place_infos = subfields_place_info;
    1018              :   // add place infos for the rest of the fields
    1019         5515 :   for (size_t i = 1; i < place_infos.size (); i++)
    1020          111 :     new_place_infos.push_back (place_infos.at (i));
    1021              : 
    1022         5404 :   return Matrix (new_rows, new_place_infos);
    1023         2702 : }
    1024              : 
    1025              : std::string
    1026            0 : Matrix::to_string () const
    1027              : {
    1028            0 :   std::string s = "[\n";
    1029            0 :   for (const MatrixRow &row : rows)
    1030            0 :     s += "row: " + row.to_string () + "\n";
    1031              : 
    1032            0 :   s += "](place_infos=[";
    1033            0 :   for (const PlaceInfo &place_info : place_infos)
    1034            0 :     s += place_info.get_type ()->as_string () + ", ";
    1035              : 
    1036            0 :   s += "])";
    1037            0 :   return s;
    1038              : }
    1039              : 
    1040              : std::string
    1041           18 : WitnessPat::to_string () const
    1042              : {
    1043           18 :   switch (ctor.get_kind ())
    1044              :     {
    1045            2 :     case Constructor::ConstructorKind::STRUCT:
    1046            2 :       {
    1047            2 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1048            2 :         TyTy::VariantDef *variant
    1049            2 :           = adt->get_variants ().at (ctor.get_variant_index ());
    1050            2 :         std::string buf;
    1051            6 :         buf += adt->get_identifier ();
    1052              : 
    1053            2 :         buf += " {";
    1054            2 :         if (!fields.empty ())
    1055            2 :           buf += " ";
    1056              : 
    1057            6 :         for (size_t i = 0; i < fields.size (); i++)
    1058              :           {
    1059           12 :             buf += variant->get_fields ().at (i)->get_name () + ": ";
    1060            8 :             buf += fields.at (i).to_string ();
    1061            4 :             if (i < fields.size () - 1)
    1062            2 :               buf += ", ";
    1063              :           }
    1064            2 :         if (!fields.empty ())
    1065            2 :           buf += " ";
    1066              : 
    1067            2 :         buf += "}";
    1068            2 :         return buf;
    1069              :       }
    1070           16 :       break;
    1071           16 :     case Constructor::ConstructorKind::VARIANT:
    1072           16 :       {
    1073           16 :         std::string buf;
    1074           16 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1075           48 :         buf += adt->get_identifier ();
    1076           16 :         TyTy::VariantDef *variant
    1077           16 :           = adt->get_variants ().at (ctor.get_variant_index ());
    1078           32 :         buf += "::" + variant->get_identifier ();
    1079              : 
    1080           16 :         switch (variant->get_variant_type ())
    1081              :           {
    1082            3 :           case TyTy::VariantDef::VariantType::UNIT:
    1083            3 :           case TyTy::VariantDef::VariantType::NUM:
    1084            3 :             {
    1085            3 :               return buf;
    1086              :             }
    1087           13 :             break;
    1088           13 :           case TyTy::VariantDef::VariantType::TUPLE:
    1089           13 :             {
    1090           13 :               buf += "(";
    1091           27 :               for (size_t i = 0; i < fields.size (); i++)
    1092              :                 {
    1093            2 :                   buf += fields.at (i).to_string ();
    1094            1 :                   if (i < fields.size () - 1)
    1095            0 :                     buf += ", ";
    1096              :                 }
    1097           13 :               buf += ")";
    1098           13 :               return buf;
    1099              :             }
    1100            0 :             break;
    1101            0 :           case TyTy::VariantDef::VariantType::STRUCT:
    1102            0 :             {
    1103            0 :               buf += " {";
    1104            0 :               if (!fields.empty ())
    1105            0 :                 buf += " ";
    1106              : 
    1107            0 :               for (size_t i = 0; i < fields.size (); i++)
    1108              :                 {
    1109            0 :                   buf += variant->get_fields ().at (i)->get_name () + ": ";
    1110            0 :                   buf += fields.at (i).to_string ();
    1111            0 :                   if (i < fields.size () - 1)
    1112            0 :                     buf += ", ";
    1113              :                 }
    1114              : 
    1115            0 :               if (!fields.empty ())
    1116            0 :                 buf += " ";
    1117              : 
    1118            0 :               buf += "}";
    1119              :             }
    1120            0 :             break;
    1121            0 :           default:
    1122            0 :             {
    1123            0 :               rust_unreachable ();
    1124              :             }
    1125            0 :             break;
    1126              :           }
    1127            0 :         return buf;
    1128           16 :       }
    1129            0 :       break;
    1130            0 :     case Constructor::ConstructorKind::INT_RANGE:
    1131            0 :       {
    1132              :         // TODO: implement
    1133            0 :         rust_unreachable ();
    1134              :       }
    1135            0 :       break;
    1136            0 :     case Constructor::ConstructorKind::WILDCARD:
    1137            0 :       {
    1138            0 :         return "_";
    1139              :       }
    1140            0 :       break;
    1141            0 :     case Constructor::ConstructorKind::REFERENCE:
    1142            0 :       {
    1143              :         // TODO: implement
    1144            0 :         rust_unreachable ();
    1145              :       }
    1146            0 :       break;
    1147            0 :     default:
    1148            0 :       {
    1149            0 :         rust_unreachable ();
    1150              :       }
    1151              :       break;
    1152              :     }
    1153              :   rust_unreachable ();
    1154              : }
    1155              : 
    1156              : void
    1157         2702 : WitnessMatrix::apply_constructor (const Constructor &ctor,
    1158              :                                   const std::set<Constructor> &missings,
    1159              :                                   TyTy::BaseType *ty)
    1160              : {
    1161         2702 :   int arity = 0;
    1162              :   // TODO: only support struct and variant ctor for now.
    1163         2702 :   switch (ctor.get_kind ())
    1164              :     {
    1165              :     case Constructor::ConstructorKind::WILDCARD:
    1166              :       {
    1167              :         arity = 0;
    1168              :       }
    1169              :       break;
    1170         1407 :     case Constructor::ConstructorKind::STRUCT:
    1171         1407 :     case Constructor::ConstructorKind::VARIANT:
    1172         1407 :       {
    1173         1407 :         if (ty->get_kind () == TyTy::TypeKind::ADT)
    1174              :           {
    1175         1407 :             TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1176         1407 :             TyTy::VariantDef *variant
    1177         1407 :               = adt->get_variants ().at (ctor.get_variant_index ());
    1178         1407 :             if (variant->get_variant_type () == TyTy::VariantDef::NUM
    1179         1407 :                 || variant->get_variant_type () == TyTy::VariantDef::UNIT)
    1180              :               arity = 0;
    1181              :             else
    1182          812 :               arity = variant->get_fields ().size ();
    1183              :           }
    1184              :       }
    1185              :       break;
    1186            0 :     default:
    1187            0 :       {
    1188            0 :         rust_unreachable ();
    1189              :       }
    1190              :     }
    1191              : 
    1192         2702 :   std::string buf;
    1193         2713 :   for (auto &stack : patstacks)
    1194              :     {
    1195           11 :       buf += "[";
    1196           18 :       for (auto &pat : stack)
    1197           21 :         buf += pat.to_string () + ", ";
    1198              : 
    1199           11 :       buf += "]\n";
    1200              :     }
    1201         2702 :   rust_debug ("witness pats:\n%s", buf.c_str ());
    1202              : 
    1203         2713 :   for (auto &stack : patstacks)
    1204              :     {
    1205           11 :       std::vector<WitnessPat> subfield;
    1206           16 :       for (int i = 0; i < arity; i++)
    1207              :         {
    1208            5 :           if (stack.empty ())
    1209            0 :             subfield.push_back (WitnessPat::make_wildcard (ty));
    1210              :           else
    1211              :             {
    1212            5 :               subfield.push_back (stack.back ());
    1213            5 :               stack.pop_back ();
    1214              :             }
    1215              :         }
    1216              : 
    1217           11 :       stack.emplace_back (ctor, subfield, ty);
    1218           11 :     }
    1219         2702 : }
    1220              : 
    1221              : void
    1222         2702 : WitnessMatrix::extend (const WitnessMatrix &other)
    1223              : {
    1224         2702 :   patstacks.insert (patstacks.end (), other.patstacks.begin (),
    1225              :                     other.patstacks.end ());
    1226         2702 : }
    1227              : 
    1228              : // forward declarations
    1229              : static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx,
    1230              :                                        HIR::Pattern &pattern,
    1231              :                                        TyTy::BaseType *scrutinee_ty);
    1232              : 
    1233              : static DeconstructedPat
    1234          856 : lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
    1235              :                      HIR::TupleStructPattern &pattern,
    1236              :                      TyTy::VariantDef *variant, Constructor &ctor)
    1237              : {
    1238          856 :   int arity = variant->get_fields ().size ();
    1239          856 :   HIR::TupleStructItems &elems = pattern.get_items ();
    1240              : 
    1241          856 :   std::vector<DeconstructedPat> fields;
    1242          856 :   switch (elems.get_item_type ())
    1243              :     {
    1244          820 :     case HIR::TupleStructItems::ItemType::NO_REST:
    1245          820 :       {
    1246          820 :         HIR::TupleStructItemsNoRest &items_no_rest
    1247              :           = static_cast<HIR::TupleStructItemsNoRest &> (elems);
    1248              : 
    1249          820 :         rust_assert (variant->get_fields ().size ()
    1250              :                      == items_no_rest.get_patterns ().size ());
    1251              : 
    1252         1628 :         for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
    1253              :           {
    1254          808 :             fields.push_back (
    1255         1616 :               lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
    1256          808 :                              variant->get_fields ().at (i)->get_field_type ()));
    1257              :           }
    1258          820 :         return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
    1259              :       }
    1260           36 :       break;
    1261           36 :     case HIR::TupleStructItems::ItemType::HAS_REST:
    1262           36 :       {
    1263           36 :         HIR::TupleStructItemsHasRest &items_has_rest
    1264              :           = static_cast<HIR::TupleStructItemsHasRest &> (elems);
    1265              : 
    1266           36 :         size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
    1267           36 :                               + items_has_rest.get_upper_patterns ().size ();
    1268              : 
    1269           36 :         rust_assert (num_patterns <= variant->num_fields ());
    1270              : 
    1271           36 :         size_t i = 0;
    1272           65 :         for (auto &pattern_member : items_has_rest.get_lower_patterns ())
    1273              :           {
    1274           29 :             fields.push_back (lower_pattern (
    1275           29 :               ctx, *pattern_member,
    1276           29 :               variant->get_fields ().at (i++)->get_field_type ()));
    1277              :           }
    1278          100 :         while (i < variant->num_fields ()
    1279          100 :                      - items_has_rest.get_upper_patterns ().size ())
    1280              :           {
    1281           64 :             fields.push_back (
    1282           64 :               DeconstructedPat::make_wildcard (pattern.get_locus ()));
    1283           64 :             i++;
    1284              :           }
    1285           50 :         for (auto &pattern_member : items_has_rest.get_upper_patterns ())
    1286              :           {
    1287           14 :             fields.push_back (lower_pattern (
    1288           14 :               ctx, *pattern_member,
    1289           14 :               variant->get_fields ().at (i++)->get_field_type ()));
    1290              :           }
    1291           36 :         return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
    1292              :       }
    1293            0 :       break;
    1294            0 :     default:
    1295            0 :       {
    1296            0 :         rust_unreachable ();
    1297              :       }
    1298              :     }
    1299          856 : }
    1300              : 
    1301              : static DeconstructedPat
    1302           93 : lower_struct_pattern (Resolver::TypeCheckContext *ctx,
    1303              :                       HIR::StructPattern &pattern, TyTy::VariantDef *variant,
    1304              :                       Constructor ctor)
    1305              : {
    1306           93 :   int arity = variant->get_fields ().size ();
    1307              : 
    1308              :   // Initialize all field patterns to wildcard.
    1309           93 :   std::vector<DeconstructedPat> fields
    1310          186 :     = std::vector<DeconstructedPat> (arity, DeconstructedPat::make_wildcard (
    1311           93 :                                               pattern.get_locus ()));
    1312              : 
    1313           93 :   std::map<std::string, int> field_map;
    1314          248 :   for (int i = 0; i < arity; i++)
    1315              :     {
    1316          155 :       auto &f = variant->get_fields ().at (i);
    1317          155 :       field_map[f->get_name ()] = i;
    1318              :     }
    1319              : 
    1320              :   // Fill in the fields with the present patterns.
    1321           93 :   HIR::StructPatternElements elems = pattern.get_struct_pattern_elems ();
    1322          245 :   for (auto &elem : elems.get_struct_pattern_fields ())
    1323              :     {
    1324          152 :       switch (elem->get_item_type ())
    1325              :         {
    1326           79 :         case HIR::StructPatternField::ItemType::IDENT:
    1327           79 :           {
    1328           79 :             HIR::StructPatternFieldIdent *ident
    1329           79 :               = static_cast<HIR::StructPatternFieldIdent *> (elem.get ());
    1330           79 :             int field_idx
    1331           79 :               = field_map.at (ident->get_identifier ().as_string ());
    1332           79 :             fields.at (field_idx)
    1333           79 :               = DeconstructedPat::make_wildcard (pattern.get_locus ());
    1334              :           }
    1335           79 :           break;
    1336           55 :         case HIR::StructPatternField::ItemType::IDENT_PAT:
    1337           55 :           {
    1338           55 :             HIR::StructPatternFieldIdentPat *ident_pat
    1339           55 :               = static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ());
    1340           55 :             int field_idx
    1341           55 :               = field_map.at (ident_pat->get_identifier ().as_string ());
    1342           55 :             fields.at (field_idx) = lower_pattern (
    1343              :               ctx, ident_pat->get_pattern (),
    1344          110 :               variant->get_fields ().at (field_idx)->get_field_type ());
    1345              :           }
    1346           55 :           break;
    1347           18 :         case HIR::StructPatternField::ItemType::TUPLE_PAT:
    1348           18 :           {
    1349           18 :             HIR::StructPatternFieldTuplePat *tuple_pat
    1350           18 :               = static_cast<HIR::StructPatternFieldTuplePat *> (elem.get ());
    1351           18 :             int field_idx = tuple_pat->get_index ();
    1352           18 :             fields.at (field_idx) = lower_pattern (
    1353              :               ctx, tuple_pat->get_tuple_pattern (),
    1354           36 :               variant->get_fields ().at (field_idx)->get_field_type ());
    1355              :           }
    1356           18 :           break;
    1357            0 :         default:
    1358            0 :           {
    1359            0 :             rust_unreachable ();
    1360              :           }
    1361              :         }
    1362              :     }
    1363              : 
    1364           93 :   return DeconstructedPat{ctor, arity, fields, pattern.get_locus ()};
    1365           93 : };
    1366              : 
    1367              : static DeconstructedPat
    1368         3484 : lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
    1369              :                TyTy::BaseType *scrutinee_ty)
    1370              : {
    1371         3484 :   HIR::Pattern::PatternType pat_type = pattern.get_pattern_type ();
    1372         3484 :   switch (pat_type)
    1373              :     {
    1374         1115 :     case HIR::Pattern::PatternType::WILDCARD:
    1375         1115 :     case HIR::Pattern::PatternType::IDENTIFIER:
    1376         1115 :       {
    1377         1115 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1378              :       }
    1379          784 :       break;
    1380          784 :     case HIR::Pattern::PatternType::PATH:
    1381          784 :       {
    1382              :         // TODO: support constants, associated constants, enum variants and
    1383              :         // structs
    1384              :         // https://doc.rust-lang.org/reference/patterns.html#path-patterns
    1385              :         // unimplemented. Treat this pattern as wildcard for now.
    1386          784 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1387              :       }
    1388           31 :       break;
    1389           31 :     case HIR::Pattern::PatternType::REFERENCE:
    1390           31 :       {
    1391              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1392           31 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1393              :       }
    1394          949 :       break;
    1395          949 :     case HIR::Pattern::PatternType::STRUCT:
    1396          949 :     case HIR::Pattern::PatternType::TUPLE_STRUCT:
    1397          949 :       {
    1398          949 :         HirId path_id = UNKNOWN_HIRID;
    1399          949 :         if (pat_type == HIR::Pattern::PatternType::STRUCT)
    1400              :           {
    1401           93 :             HIR::StructPattern &struct_pattern
    1402              :               = static_cast<HIR::StructPattern &> (pattern);
    1403           93 :             path_id = struct_pattern.get_path ().get_mappings ().get_hirid ();
    1404              :           }
    1405              :         else
    1406              :           {
    1407          856 :             HIR::TupleStructPattern &tuple_pattern
    1408              :               = static_cast<HIR::TupleStructPattern &> (pattern);
    1409          856 :             path_id = tuple_pattern.get_path ().get_mappings ().get_hirid ();
    1410              :           }
    1411              : 
    1412          949 :         rust_assert (scrutinee_ty->get_kind () == TyTy::TypeKind::ADT);
    1413          949 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (scrutinee_ty);
    1414              : 
    1415          949 :         Constructor ctor = Constructor::make_struct ();
    1416          949 :         TyTy::VariantDef *variant;
    1417          949 :         if (adt->is_struct_struct () || adt->is_tuple_struct ())
    1418           84 :           variant = adt->get_variants ().at (0);
    1419          865 :         else if (adt->is_enum ())
    1420              :           {
    1421          865 :             HirId variant_id = UNKNOWN_HIRID;
    1422          865 :             bool ok = ctx->lookup_variant_definition (path_id, &variant_id);
    1423          865 :             rust_assert (ok);
    1424              : 
    1425          865 :             int variant_idx;
    1426          865 :             ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_idx);
    1427          865 :             rust_assert (ok);
    1428              : 
    1429          865 :             ctor = Constructor::make_variant (variant_idx);
    1430              :           }
    1431              :         else
    1432              :           {
    1433            0 :             rust_unreachable ();
    1434              :           }
    1435          949 :         rust_assert (variant->get_variant_type ()
    1436              :                        == TyTy::VariantDef::VariantType::TUPLE
    1437              :                      || variant->get_variant_type ()
    1438              :                           == TyTy::VariantDef::VariantType::STRUCT);
    1439              : 
    1440          949 :         if (pat_type == HIR::Pattern::PatternType::STRUCT)
    1441              :           {
    1442           93 :             HIR::StructPattern &struct_pattern
    1443              :               = static_cast<HIR::StructPattern &> (pattern);
    1444           93 :             return lower_struct_pattern (ctx, struct_pattern, variant, ctor);
    1445              :           }
    1446              :         else
    1447              :           {
    1448          856 :             HIR::TupleStructPattern &tuple_pattern
    1449              :               = static_cast<HIR::TupleStructPattern &> (pattern);
    1450          856 :             return lower_tuple_pattern (ctx, tuple_pattern, variant, ctor);
    1451              :           }
    1452              :       }
    1453          133 :       break;
    1454          133 :     case HIR::Pattern::PatternType::TUPLE:
    1455          133 :       {
    1456              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1457          133 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1458              :       }
    1459           75 :       break;
    1460           75 :     case HIR::Pattern::PatternType::SLICE:
    1461           75 :       {
    1462              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1463           75 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1464              :       }
    1465          145 :       break;
    1466          145 :     case HIR::Pattern::PatternType::ALT:
    1467          145 :       {
    1468              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1469          145 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1470              :       }
    1471          208 :       break;
    1472          208 :     case HIR::Pattern::PatternType::LITERAL:
    1473          208 :       {
    1474              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1475          208 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1476              :       }
    1477           44 :       break;
    1478           44 :     case HIR::Pattern::PatternType::RANGE:
    1479           44 :       {
    1480              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1481           44 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1482              :       }
    1483            0 :       break;
    1484            0 :     case HIR::Pattern::PatternType::GROUPED:
    1485            0 :       {
    1486              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1487            0 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1488              :       }
    1489            0 :       break;
    1490            0 :     default:
    1491            0 :       {
    1492            0 :         rust_unreachable ();
    1493              :       }
    1494              :     }
    1495              : }
    1496              : 
    1497              : static MatchArm
    1498         2560 : lower_arm (Resolver::TypeCheckContext *ctx, HIR::MatchCase &arm,
    1499              :            TyTy::BaseType *scrutinee_ty)
    1500              : {
    1501         2560 :   rust_assert (arm.get_arm ().get_pattern () != nullptr);
    1502              : 
    1503         2560 :   DeconstructedPat pat
    1504         2560 :     = lower_pattern (ctx, *arm.get_arm ().get_pattern (), scrutinee_ty);
    1505         2560 :   return MatchArm (pat, arm.get_arm ().has_match_arm_guard ());
    1506         2560 : }
    1507              : 
    1508              : std::pair<std::set<Constructor>, std::set<Constructor>>
    1509         1996 : split_constructors (std::vector<Constructor> &ctors, PlaceInfo &place_info)
    1510              : {
    1511         1996 :   bool all_wildcard = true;
    1512         6411 :   for (auto &ctor : ctors)
    1513              :     {
    1514         4415 :       if (!ctor.is_wildcard ())
    1515          951 :         all_wildcard = false;
    1516              :     }
    1517              : 
    1518              :   // first pass for the case that all patterns are wildcard
    1519         1996 :   if (all_wildcard)
    1520         2590 :     return std::make_pair (std::set<Constructor> (
    1521         2590 :                              {Constructor::make_wildcard ()}),
    1522         3885 :                            std::set<Constructor> ());
    1523              : 
    1524              :   // TODO: only support enums and structs for now.
    1525          701 :   TyTy::BaseType *ty = place_info.get_type ();
    1526          701 :   rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
    1527          701 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1528          701 :   rust_assert (adt->is_enum () || adt->is_struct_struct ()
    1529              :                || adt->is_tuple_struct ());
    1530              : 
    1531          701 :   std::set<Constructor> universe;
    1532          701 :   if (adt->is_enum ())
    1533              :     {
    1534         1998 :       for (size_t i = 0; i < adt->get_variants ().size (); i++)
    1535         1352 :         universe.insert (Constructor::make_variant (i));
    1536              :     }
    1537           55 :   else if (adt->is_struct_struct () || adt->is_tuple_struct ())
    1538              :     {
    1539           55 :       universe.insert (Constructor::make_struct ());
    1540              :     }
    1541              : 
    1542          701 :   std::set<Constructor> present;
    1543         1572 :   for (auto &ctor : ctors)
    1544              :     {
    1545         1485 :       if (ctor.is_wildcard ())
    1546         1228 :         return std::make_pair (universe, std::set<Constructor> ());
    1547              :       else
    1548          871 :         present.insert (ctor);
    1549              :     }
    1550              : 
    1551           87 :   std::set<Constructor> missing;
    1552           87 :   std::set_difference (universe.begin (), universe.end (), present.begin (),
    1553              :                        present.end (), std::inserter (missing, missing.end ()));
    1554          174 :   return std::make_pair (universe, missing);
    1555          788 : }
    1556              : 
    1557              : // The core of the algorithm. It computes the usefulness and exhaustiveness of a
    1558              : // given matrix recursively.
    1559              : // TODO: calculate usefulness
    1560              : static WitnessMatrix
    1561         3817 : compute_exhaustiveness_and_usefulness (Resolver::TypeCheckContext *ctx,
    1562              :                                        Matrix &matrix)
    1563              : {
    1564         3817 :   rust_debug ("call compute_exhaustiveness_and_usefulness");
    1565         3817 :   rust_debug ("matrix: %s", matrix.to_string ().c_str ());
    1566              : 
    1567         3817 :   if (matrix.get_rows ().empty ())
    1568              :     {
    1569              :       // no rows left. This means a non-exhaustive pattern.
    1570            6 :       rust_debug ("non-exhaustive subpattern found");
    1571            6 :       return WitnessMatrix::make_unit ();
    1572              :     }
    1573              : 
    1574              :   // Base case: there are no columns in matrix.
    1575         3811 :   if (matrix.get_place_infos ().empty ())
    1576         1815 :     return WitnessMatrix::make_empty ();
    1577              : 
    1578         1996 :   std::vector<Constructor> heads;
    1579         6411 :   for (auto head : matrix.heads ())
    1580        10826 :     heads.push_back (head.ctor ());
    1581              : 
    1582              :   // TODO: not sure missing ctors need to be calculated
    1583         1996 :   auto ctors_and_missings
    1584         1996 :     = split_constructors (heads, matrix.get_place_infos ().at (0));
    1585         1996 :   std::set<Constructor> ctors = ctors_and_missings.first;
    1586         1996 :   std::set<Constructor> missings = ctors_and_missings.second;
    1587              : 
    1588         1996 :   WitnessMatrix ret = WitnessMatrix::make_empty ();
    1589         4698 :   for (auto &ctor : ctors)
    1590              :     {
    1591         2702 :       rust_debug ("specialize with %s", ctor.to_string ().c_str ());
    1592              :       // TODO: Instead of creating new matrix, we can change the original matrix
    1593              :       // and use it for sub-pattern matching. It will significantly reduce
    1594              :       // memory usage.
    1595         2702 :       Matrix spec_matrix = matrix.specialize (ctor);
    1596              : 
    1597         2702 :       WitnessMatrix witness
    1598         2702 :         = compute_exhaustiveness_and_usefulness (ctx, spec_matrix);
    1599              : 
    1600         2702 :       TyTy::BaseType *ty = matrix.get_place_infos ().at (0).get_type ();
    1601         2702 :       witness.apply_constructor (ctor, missings, ty);
    1602         2702 :       ret.extend (witness);
    1603         5404 :     }
    1604              : 
    1605         1996 :   return ret;
    1606         1996 : }
    1607              : 
    1608              : static void
    1609         1115 : emit_exhaustiveness_error (Resolver::TypeCheckContext *ctx,
    1610              :                            HIR::MatchExpr &expr, WitnessMatrix &witness)
    1611              : {
    1612         1115 :   TyTy::BaseType *scrutinee_ty;
    1613         1115 :   bool ok
    1614         1115 :     = ctx->lookup_type (expr.get_scrutinee_expr ().get_mappings ().get_hirid (),
    1615              :                         &scrutinee_ty);
    1616         1115 :   rust_assert (ok);
    1617              : 
    1618         1115 :   if (!witness.empty ())
    1619              :     {
    1620            4 :       std::stringstream buf;
    1621           14 :       for (size_t i = 0; i < witness.get_stacks ().size (); i++)
    1622              :         {
    1623            6 :           auto &stack = witness.get_stacks ().at (i);
    1624            6 :           WitnessPat w = WitnessPat::make_wildcard (scrutinee_ty);
    1625            6 :           if (!stack.empty ())
    1626            6 :             w = stack.at (0);
    1627              : 
    1628            6 :           rust_debug ("Witness[%d]: %s", (int) i, w.to_string ().c_str ());
    1629           12 :           buf << "'" << w.to_string () << "'";
    1630            6 :           if (i != witness.get_stacks ().size () - 1)
    1631            2 :             buf << " and ";
    1632            6 :         }
    1633            4 :       rust_error_at (expr.get_scrutinee_expr ().get_locus (),
    1634              :                      "non-exhaustive patterns: %s not covered",
    1635            4 :                      buf.str ().c_str ());
    1636            4 :     }
    1637              :   else
    1638              :     {
    1639         1111 :       rust_debug ("no witness found");
    1640              :     }
    1641         1115 : }
    1642              : 
    1643              : // Entry point for computing match usefulness and check exhaustiveness
    1644              : void
    1645         1120 : check_match_usefulness (Resolver::TypeCheckContext *ctx,
    1646              :                         TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr)
    1647              : {
    1648         1120 :   if (!expr.has_match_arms ())
    1649            5 :     return;
    1650              : 
    1651              :   // Lower the arms to a more convenient representation.
    1652         1115 :   std::vector<MatrixRow> rows;
    1653         3675 :   for (auto &arm : expr.get_match_cases ())
    1654              :     {
    1655         2560 :       PatStack pats;
    1656         2560 :       MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty);
    1657         2560 :       PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ());
    1658         2560 :       pats.push (pat);
    1659         2560 :       rows.emplace_back (pats, lowered.has_guard ());
    1660         2560 :     }
    1661              : 
    1662         1115 :   std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}};
    1663         2230 :   Matrix matrix{rows, place_infos};
    1664              : 
    1665         1115 :   WitnessMatrix witness = compute_exhaustiveness_and_usefulness (ctx, matrix);
    1666              : 
    1667         1115 :   emit_exhaustiveness_error (ctx, expr, witness);
    1668         2230 : }
    1669              : 
    1670              : } // namespace Analysis
    1671              : } // 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.