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: 75.2 % 910 684
Test Date: 2026-08-22 16:33:35 Functions: 59.4 % 155 92
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         4408 : PatternChecker::PatternChecker ()
      36         4408 :   : tyctx (*Resolver::TypeCheckContext::get ()),
      37         4408 :     resolver (Resolver2_0::FinalizedNameResolutionContext::get ()),
      38         8816 :     mappings (Analysis::Mappings::get ())
      39         4408 : {}
      40              : 
      41              : void
      42         4408 : PatternChecker::go (HIR::Crate &crate)
      43              : {
      44         4408 :   rust_debug ("started pattern check");
      45        22582 :   for (auto &item : crate.get_items ())
      46        18179 :     item->accept_vis (*this);
      47         4403 :   rust_debug ("finished pattern check");
      48         4403 : }
      49              : 
      50              : void
      51            0 : PatternChecker::visit (Lifetime &)
      52            0 : {}
      53              : 
      54              : void
      55            0 : PatternChecker::visit (LifetimeParam &)
      56            0 : {}
      57              : 
      58              : void
      59        34424 : PatternChecker::visit (PathInExpression &path)
      60        34424 : {}
      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        19649 : PatternChecker::visit (LiteralExpr &)
      88        19649 : {}
      89              : 
      90              : void
      91         2009 : PatternChecker::visit (BorrowExpr &expr)
      92              : {
      93         2009 :   expr.get_expr ().accept_vis (*this);
      94         2009 : }
      95              : 
      96              : void
      97         3912 : PatternChecker::visit (DereferenceExpr &expr)
      98              : {
      99         3912 :   expr.get_expr ().accept_vis (*this);
     100         3912 : }
     101              : 
     102              : void
     103            0 : PatternChecker::visit (ErrorPropagationExpr &expr)
     104              : {
     105            0 :   expr.get_expr ().accept_vis (*this);
     106            0 : }
     107              : 
     108              : void
     109          584 : PatternChecker::visit (NegationExpr &expr)
     110              : {
     111          584 :   expr.get_expr ().accept_vis (*this);
     112          584 : }
     113              : 
     114              : void
     115         3261 : PatternChecker::visit (ArithmeticOrLogicalExpr &expr)
     116              : {
     117         3261 :   expr.get_lhs ().accept_vis (*this);
     118         3261 :   expr.get_rhs ().accept_vis (*this);
     119         3261 : }
     120              : 
     121              : void
     122         3557 : PatternChecker::visit (ComparisonExpr &expr)
     123              : {
     124         3557 :   expr.get_lhs ().accept_vis (*this);
     125         3557 :   expr.get_rhs ().accept_vis (*this);
     126         3557 : }
     127              : 
     128              : void
     129          404 : PatternChecker::visit (LazyBooleanExpr &expr)
     130              : {
     131          404 :   expr.get_lhs ().accept_vis (*this);
     132          404 :   expr.get_rhs ().accept_vis (*this);
     133          404 : }
     134              : 
     135              : void
     136         5266 : PatternChecker::visit (TypeCastExpr &expr)
     137              : {
     138         5266 :   expr.get_expr ().accept_vis (*this);
     139         5266 : }
     140              : 
     141              : void
     142         2475 : PatternChecker::visit (AssignmentExpr &expr)
     143              : {
     144         2475 :   expr.get_lhs ().accept_vis (*this);
     145         2475 :   expr.get_rhs ().accept_vis (*this);
     146         2475 : }
     147              : 
     148              : void
     149          696 : PatternChecker::visit (CompoundAssignmentExpr &expr)
     150              : {
     151          696 :   expr.get_lhs ().accept_vis (*this);
     152          696 :   expr.get_rhs ().accept_vis (*this);
     153          696 : }
     154              : 
     155              : void
     156          293 : PatternChecker::visit (GroupedExpr &expr)
     157              : {
     158          293 :   expr.get_expr_in_parens ().accept_vis (*this);
     159          293 : }
     160              : 
     161              : void
     162          291 : PatternChecker::visit (ArrayElemsValues &elems)
     163              : {
     164         1765 :   for (auto &elem : elems.get_values ())
     165         1474 :     elem->accept_vis (*this);
     166          291 : }
     167              : 
     168              : void
     169          113 : PatternChecker::visit (ArrayElemsCopied &elems)
     170              : {
     171          113 :   elems.get_elem_to_copy ().accept_vis (*this);
     172          113 : }
     173              : 
     174              : void
     175          404 : PatternChecker::visit (ArrayExpr &expr)
     176              : {
     177          404 :   expr.get_internal_elements ().accept_vis (*this);
     178          404 : }
     179              : 
     180              : void
     181          287 : PatternChecker::visit (ArrayIndexExpr &expr)
     182              : {
     183          287 :   expr.get_array_expr ().accept_vis (*this);
     184          287 :   expr.get_index_expr ().accept_vis (*this);
     185          287 : }
     186              : 
     187              : void
     188          558 : PatternChecker::visit (TupleExpr &expr)
     189              : {
     190         1529 :   for (auto &elem : expr.get_tuple_elems ())
     191          971 :     elem->accept_vis (*this);
     192          558 : }
     193              : 
     194              : void
     195          887 : PatternChecker::visit (TupleIndexExpr &expr)
     196              : {
     197          887 :   expr.get_tuple_expr ().accept_vis (*this);
     198          887 : }
     199              : 
     200              : void
     201           79 : PatternChecker::visit (StructExprStruct &)
     202           79 : {}
     203              : 
     204              : void
     205          229 : PatternChecker::visit (StructExprFieldIdentifier &)
     206          229 : {}
     207              : 
     208              : void
     209         2666 : PatternChecker::visit (StructExprFieldIdentifierValue &field)
     210              : {
     211         2666 :   field.get_value ().accept_vis (*this);
     212         2666 : }
     213              : 
     214              : void
     215           42 : PatternChecker::visit (StructExprFieldIndexValue &field)
     216              : {
     217           42 :   field.get_value ().accept_vis (*this);
     218           42 : }
     219              : 
     220              : void
     221         1352 : PatternChecker::visit (StructExprStructFields &expr)
     222              : {
     223         4289 :   for (auto &field : expr.get_fields ())
     224         2937 :     field->accept_vis (*this);
     225         1352 : }
     226              : 
     227              : void
     228            0 : PatternChecker::visit (StructExprStructBase &)
     229            0 : {}
     230              : 
     231              : void
     232        12247 : PatternChecker::visit (CallExpr &expr)
     233              : {
     234        12247 :   if (!expr.has_fnexpr ())
     235              :     return;
     236              : 
     237        12247 :   NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid ();
     238        12247 :   NodeId ref_node_id;
     239        12247 :   if (auto id = resolver.lookup (ast_node_id, Resolver2_0::Namespace::Values))
     240        12177 :     ref_node_id = *id;
     241              :   else
     242           70 :     return;
     243              : 
     244        12177 :   if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id))
     245              :     {
     246        12177 :       if (expr.has_params ())
     247        23514 :         for (auto &arg : expr.get_arguments ())
     248        13792 :           arg->accept_vis (*this);
     249              :     }
     250              :   else
     251              :     {
     252            0 :       rust_unreachable ();
     253              :     }
     254              : }
     255              : 
     256              : void
     257         3032 : PatternChecker::visit (MethodCallExpr &expr)
     258              : {
     259         3032 :   expr.get_receiver ().accept_vis (*this);
     260              : 
     261         5087 :   for (auto &arg : expr.get_arguments ())
     262         2055 :     arg->accept_vis (*this);
     263         3032 : }
     264              : 
     265              : void
     266         5649 : PatternChecker::visit (FieldAccessExpr &expr)
     267              : {
     268         5649 :   expr.get_receiver_expr ().accept_vis (*this);
     269         5649 : }
     270              : 
     271              : void
     272           53 : PatternChecker::visit (ClosureExpr &expr)
     273              : {
     274           53 :   expr.get_expr ().accept_vis (*this);
     275           53 : }
     276              : 
     277              : void
     278        23061 : PatternChecker::visit (BlockExpr &expr)
     279              : {
     280        47221 :   for (auto &stmt : expr.get_statements ())
     281        24160 :     stmt->accept_vis (*this);
     282              : 
     283        23061 :   if (expr.has_expr ())
     284        16366 :     expr.get_final_expr ().accept_vis (*this);
     285        23061 : }
     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           22 : PatternChecker::visit (ContinueExpr &)
     301           22 : {}
     302              : 
     303              : void
     304           97 : PatternChecker::visit (BreakExpr &expr)
     305              : {
     306           97 :   if (expr.has_break_expr ())
     307           19 :     expr.get_expr ().accept_vis (*this);
     308           97 : }
     309              : 
     310              : void
     311           66 : PatternChecker::visit (RangeFromToExpr &expr)
     312              : {
     313           66 :   expr.get_from_expr ().accept_vis (*this);
     314           66 :   expr.get_to_expr ().accept_vis (*this);
     315           66 : }
     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            1 : PatternChecker::visit (BoxExpr &expr)
     341              : {
     342            1 :   expr.get_expr ().accept_vis (*this);
     343            1 : }
     344              : 
     345              : void
     346          540 : PatternChecker::visit (ReturnExpr &expr)
     347              : {
     348          540 :   if (expr.has_return_expr ())
     349          507 :     expr.get_expr ().accept_vis (*this);
     350          540 : }
     351              : 
     352              : void
     353         3691 : PatternChecker::visit (UnsafeBlockExpr &expr)
     354              : {
     355         3691 :   expr.get_block_expr ().accept_vis (*this);
     356         3691 : }
     357              : 
     358              : void
     359          136 : PatternChecker::visit (LoopExpr &expr)
     360              : {
     361          136 :   expr.get_loop_block ().accept_vis (*this);
     362          136 : }
     363              : 
     364              : void
     365           78 : PatternChecker::visit (WhileLoopExpr &expr)
     366              : {
     367           78 :   expr.get_predicate_expr ().accept_vis (*this);
     368           78 :   expr.get_loop_block ().accept_vis (*this);
     369           78 : }
     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         1247 : PatternChecker::visit (IfExpr &expr)
     380              : {
     381         1247 :   expr.get_if_condition ().accept_vis (*this);
     382         1247 :   expr.get_if_block ().accept_vis (*this);
     383         1247 : }
     384              : 
     385              : void
     386         1258 : PatternChecker::visit (IfExprConseqElse &expr)
     387              : {
     388         1258 :   expr.get_if_condition ().accept_vis (*this);
     389         1258 :   expr.get_if_block ().accept_vis (*this);
     390         1258 :   expr.get_else_block ().accept_vis (*this);
     391         1258 : }
     392              : 
     393              : void
     394         1086 : PatternChecker::visit (MatchExpr &expr)
     395              : {
     396         1086 :   expr.get_scrutinee_expr ().accept_vis (*this);
     397              : 
     398         3583 :   for (auto &match_arm : expr.get_match_cases ())
     399         2497 :     match_arm.get_expr ().accept_vis (*this);
     400              : 
     401              :   // match expressions are only an entrypoint
     402         1086 :   TyTy::BaseType *scrutinee_ty;
     403         1086 :   bool ok = tyctx.lookup_type (
     404         1086 :     expr.get_scrutinee_expr ().get_mappings ().get_hirid (), &scrutinee_ty);
     405         1086 :   rust_assert (ok);
     406              : 
     407         1086 :   check_match_usefulness (&tyctx, scrutinee_ty, expr);
     408         1086 : }
     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         1176 : PatternChecker::visit (Module &module)
     452              : {
     453         4995 :   for (auto &item : module.get_items ())
     454         3819 :     item->accept_vis (*this);
     455         1176 : }
     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        13386 : PatternChecker::visit (Function &function)
     479              : {
     480        19706 :   for (auto &param : function.get_function_params ())
     481              :     {
     482         6325 :       TyTy::BaseType *param_ty;
     483         6325 :       bool ok
     484         6325 :         = tyctx.lookup_type (param.get_mappings ().get_hirid (), &param_ty);
     485         6325 :       rust_assert (ok);
     486              : 
     487         6325 :       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        13381 :   function.get_definition ().accept_vis (*this);
     492        13381 : }
     493              : 
     494              : void
     495         1236 : PatternChecker::visit (TypeAlias &)
     496         1236 : {}
     497              : 
     498              : void
     499         1524 : PatternChecker::visit (StructStruct &)
     500         1524 : {}
     501              : 
     502              : void
     503          937 : PatternChecker::visit (TupleStruct &)
     504          937 : {}
     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          506 : PatternChecker::visit (Enum &)
     524          506 : {}
     525              : 
     526              : void
     527          102 : PatternChecker::visit (Union &)
     528          102 : {}
     529              : 
     530              : void
     531          519 : PatternChecker::visit (ConstantItem &const_item)
     532              : {
     533          519 :   const_item.get_expr ().accept_vis (*this);
     534          519 : }
     535              : 
     536              : void
     537           53 : PatternChecker::visit (StaticItem &static_item)
     538              : {
     539           53 :   static_item.get_expr ().accept_vis (*this);
     540           53 : }
     541              : 
     542              : void
     543         2520 : PatternChecker::visit (TraitItemFunc &item)
     544              : {
     545         2520 :   if (item.has_definition ())
     546          851 :     item.get_block_expr ().accept_vis (*this);
     547         2520 : }
     548              : 
     549              : void
     550           31 : PatternChecker::visit (TraitItemConst &item)
     551              : {
     552           31 :   if (item.has_expr ())
     553            7 :     item.get_expr ().accept_vis (*this);
     554           31 : }
     555              : 
     556              : void
     557          711 : PatternChecker::visit (TraitItemType &)
     558          711 : {}
     559              : 
     560              : void
     561         3783 : PatternChecker::visit (Trait &trait)
     562              : {
     563         7045 :   for (auto &item : trait.get_trait_items ())
     564         3262 :     item->accept_vis (*this);
     565         3783 : }
     566              : 
     567              : void
     568         5649 : PatternChecker::visit (ImplBlock &impl)
     569              : {
     570        13800 :   for (auto &item : impl.get_impl_items ())
     571         8151 :     item->accept_vis (*this);
     572         5649 : }
     573              : 
     574              : void
     575            1 : PatternChecker::visit (ExternalStaticItem &)
     576            1 : {}
     577              : 
     578              : void
     579         2546 : PatternChecker::visit (ExternalFunctionItem &)
     580         2546 : {}
     581              : 
     582              : void
     583            0 : PatternChecker::visit (ExternalTypeItem &)
     584            0 : {}
     585              : 
     586              : void
     587         1661 : PatternChecker::visit (ExternBlock &block)
     588              : {
     589              :   // FIXME: Do we need to do this?
     590         4208 :   for (auto &item : block.get_extern_items ())
     591         2547 :     item->accept_vis (*this);
     592         1661 : }
     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        12823 : PatternChecker::visit (LetStmt &stmt)
     688              : {
     689        12823 :   if (stmt.has_init_expr ())
     690        11683 :     stmt.get_init_expr ().accept_vis (*this);
     691              : 
     692              :   // skip let-else (allows refutable patterns)
     693        12823 :   if (stmt.has_else_expr ())
     694            5 :     return;
     695              : 
     696        12818 :   TyTy::BaseType *binding_ty;
     697        12818 :   bool ok = tyctx.lookup_type (stmt.get_pattern ().get_mappings ().get_hirid (),
     698              :                                &binding_ty);
     699        12818 :   if (!ok)
     700              :     return; // type-check failed earlier
     701              : 
     702        12818 :   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        10909 : PatternChecker::visit (ExprStmt &stmt)
     709              : {
     710        10909 :   stmt.get_expr ().accept_vis (*this);
     711        10909 : }
     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        15878 : Constructor::is_covered_by (const Constructor &o) const
     763              : {
     764        15878 :   if (o.kind == ConstructorKind::WILDCARD)
     765              :     return true;
     766              : 
     767         3689 :   switch (kind)
     768              :     {
     769         3437 :     case ConstructorKind::VARIANT:
     770         3437 :       {
     771         3437 :         rust_assert (kind == ConstructorKind::VARIANT);
     772         3437 :         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         2920 : Constructor::operator< (const Constructor &o) const
     803              : {
     804         2920 :   if (kind != o.kind)
     805            0 :     return kind < o.kind;
     806              : 
     807         2920 :   switch (kind)
     808              :     {
     809         2830 :     case ConstructorKind::VARIANT:
     810         2830 :       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        21050 : Constructor::to_string () const
     826              : {
     827        21050 :   switch (kind)
     828              :     {
     829          346 :     case ConstructorKind::STRUCT:
     830          346 :       return "STRUCT";
     831         5119 :     case ConstructorKind::VARIANT:
     832        10238 :       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        15585 :     case ConstructorKind::WILDCARD:
     837        15585 :       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         4982 : DeconstructedPat::specialize (const Constructor &other_ctor,
     847              :                               int other_ctor_arity) const
     848              : {
     849         4982 :   rust_assert (other_ctor.is_covered_by (ctor));
     850         4982 :   if (ctor.is_wildcard ())
     851         4063 :     return std::vector<DeconstructedPat> (
     852              :       other_ctor_arity,
     853         4063 :       DeconstructedPat (Constructor::make_wildcard (), locus));
     854              : 
     855          919 :   return fields;
     856              : }
     857              : 
     858              : std::string
     859        13456 : DeconstructedPat::to_string () const
     860              : {
     861        26912 :   std::string s = ctor.to_string () + "[";
     862        15535 :   for (auto &f : fields)
     863         6237 :     s += f.to_string () + ", ";
     864              : 
     865        40368 :   s += "](arity=" + std::to_string (arity) + ")";
     866        13456 :   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         4982 : PatOrWild::specialize (const Constructor &other_ctor,
     880              :                        int other_ctor_arity) const
     881              : {
     882         4982 :   if (pat.has_value ())
     883              :     {
     884         4982 :       auto v = pat.value ().specialize (other_ctor, other_ctor_arity);
     885         4982 :       std::vector<PatOrWild> ret;
     886         6787 :       for (auto &pat : v)
     887         3610 :         ret.push_back (PatOrWild::make_pattern (pat));
     888              : 
     889         4982 :       return ret;
     890         4982 :     }
     891              :   else
     892              :     {
     893            0 :       return std::vector<PatOrWild> (other_ctor_arity,
     894            0 :                                      PatOrWild::make_wildcard ());
     895              :     }
     896              : }
     897              : 
     898              : std::string
     899        11377 : PatOrWild::to_string () const
     900              : {
     901        11377 :   if (pat.has_value ())
     902        11377 :     return pat.value ().to_string ();
     903              :   else
     904            0 :     return "Wild";
     905              : }
     906              : 
     907              : void
     908         4982 : PatStack::pop_head_constructor (const Constructor &other_ctor,
     909              :                                 int other_ctor_arity)
     910              : {
     911         4982 :   rust_assert (!pats.empty ());
     912         4982 :   rust_assert (other_ctor.is_covered_by (head ().ctor ()));
     913              : 
     914         4982 :   PatOrWild &hd = head ();
     915         4982 :   auto v = hd.specialize (other_ctor, other_ctor_arity);
     916         4982 :   {
     917         4982 :     std::string s = "[";
     918         6787 :     for (auto &pat : v)
     919         5415 :       s += pat.to_string () + ", ";
     920         4982 :     s += "]";
     921              : 
     922         4982 :     rust_debug ("specialize %s with %s to %s", hd.to_string ().c_str (),
     923              :                 other_ctor.to_string ().c_str (), s.c_str ());
     924         4982 :   }
     925         4982 :   pop_head ();
     926         6787 :   for (auto &pat : v)
     927         1805 :     pats.push_back (pat);
     928         4982 : }
     929              : 
     930              : std::string
     931         7479 : MatrixRow::to_string () const
     932              : {
     933         7479 :   std::string s;
     934        12069 :   for (const PatOrWild &pat : pats.get_subpatterns ())
     935        13770 :     s += pat.to_string () + ", ";
     936         7479 :   return s;
     937              : }
     938              : 
     939              : std::vector<PlaceInfo>
     940         2612 : PlaceInfo::specialize (const Constructor &c) const
     941              : {
     942         2612 :   switch (c.get_kind ())
     943              :     {
     944         1253 :     case Constructor::ConstructorKind::WILDCARD:
     945         1253 :     case Constructor::ConstructorKind::INT_RANGE:
     946         1253 :       {
     947         1253 :         return {};
     948              :       }
     949         1359 :       break;
     950         1359 :     case Constructor::ConstructorKind::STRUCT:
     951         1359 :     case Constructor::ConstructorKind::VARIANT:
     952         1359 :       {
     953         1359 :         rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
     954         1359 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
     955         1359 :         switch (adt->get_adt_kind ())
     956              :           {
     957         1359 :           case TyTy::ADTType::ADTKind::ENUM:
     958         1359 :           case TyTy::ADTType::ADTKind::STRUCT_STRUCT:
     959         1359 :           case TyTy::ADTType::ADTKind::TUPLE_STRUCT:
     960         1359 :             {
     961         1359 :               TyTy::VariantDef *variant
     962         1359 :                 = adt->get_variants ().at (c.get_variant_index ());
     963         1359 :               if (variant->get_variant_type ()
     964              :                     == TyTy::VariantDef::VariantType::NUM
     965         1359 :                   || variant->get_variant_type ()
     966              :                        == TyTy::VariantDef::VariantType::UNIT)
     967          579 :                 return {};
     968              : 
     969          780 :               std::vector<PlaceInfo> new_place_infos;
     970         1625 :               for (auto &field : variant->get_fields ())
     971          845 :                 new_place_infos.push_back (field->get_field_type ());
     972              : 
     973          780 :               return new_place_infos;
     974          780 :             }
     975            0 :             break;
     976            0 :           case TyTy::ADTType::ADTKind::UNION:
     977            0 :             {
     978              :               // TODO: support unions
     979            0 :               rust_unreachable ();
     980              :             }
     981              :           }
     982              :       }
     983            0 :       break;
     984            0 :     default:
     985            0 :       {
     986            0 :         rust_unreachable ();
     987              :       }
     988            0 :       break;
     989              :     }
     990              : 
     991            0 :   rust_unreachable ();
     992              : }
     993              : 
     994              : Matrix
     995         2612 : Matrix::specialize (const Constructor &ctor) const
     996              : {
     997         2612 :   auto subfields_place_info = place_infos.at (0).specialize (ctor);
     998              : 
     999         2612 :   std::vector<MatrixRow> new_rows;
    1000         8526 :   for (const MatrixRow &row : rows)
    1001              :     {
    1002         5914 :       PatStack pats = row.get_pats_clone ();
    1003         5914 :       const PatOrWild &hd = pats.head ();
    1004         5914 :       if (ctor.is_covered_by (hd.ctor ()))
    1005              :         {
    1006         4982 :           pats.pop_head_constructor (ctor, subfields_place_info.size ());
    1007         4982 :           new_rows.emplace_back (pats, row.is_under_guard ());
    1008              :         }
    1009         5914 :     }
    1010              : 
    1011         2612 :   if (place_infos.empty ())
    1012            0 :     return Matrix (new_rows, {});
    1013              : 
    1014              :   // push subfields of the first fields after specialization
    1015         2612 :   std::vector<PlaceInfo> new_place_infos = subfields_place_info;
    1016              :   // add place infos for the rest of the fields
    1017         5335 :   for (size_t i = 1; i < place_infos.size (); i++)
    1018          111 :     new_place_infos.push_back (place_infos.at (i));
    1019              : 
    1020         5224 :   return Matrix (new_rows, new_place_infos);
    1021         2612 : }
    1022              : 
    1023              : std::string
    1024         3693 : Matrix::to_string () const
    1025              : {
    1026         3693 :   std::string s = "[\n";
    1027        11172 :   for (const MatrixRow &row : rows)
    1028        22437 :     s += "row: " + row.to_string () + "\n";
    1029              : 
    1030         3693 :   s += "](place_infos=[";
    1031         5730 :   for (const PlaceInfo &place_info : place_infos)
    1032         6111 :     s += place_info.get_type ()->as_string () + ", ";
    1033              : 
    1034         3693 :   s += "])";
    1035         3693 :   return s;
    1036              : }
    1037              : 
    1038              : std::string
    1039           29 : WitnessPat::to_string () const
    1040              : {
    1041           29 :   switch (ctor.get_kind ())
    1042              :     {
    1043            4 :     case Constructor::ConstructorKind::STRUCT:
    1044            4 :       {
    1045            4 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1046            4 :         TyTy::VariantDef *variant
    1047            4 :           = adt->get_variants ().at (ctor.get_variant_index ());
    1048            4 :         std::string buf;
    1049           12 :         buf += adt->get_identifier ();
    1050              : 
    1051            4 :         buf += " {";
    1052            4 :         if (!fields.empty ())
    1053            4 :           buf += " ";
    1054              : 
    1055           12 :         for (size_t i = 0; i < fields.size (); i++)
    1056              :           {
    1057           24 :             buf += variant->get_fields ().at (i)->get_name () + ": ";
    1058           16 :             buf += fields.at (i).to_string ();
    1059            8 :             if (i < fields.size () - 1)
    1060            4 :               buf += ", ";
    1061              :           }
    1062            4 :         if (!fields.empty ())
    1063            4 :           buf += " ";
    1064              : 
    1065            4 :         buf += "}";
    1066            4 :         return buf;
    1067              :       }
    1068           25 :       break;
    1069           25 :     case Constructor::ConstructorKind::VARIANT:
    1070           25 :       {
    1071           25 :         std::string buf;
    1072           25 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1073           75 :         buf += adt->get_identifier ();
    1074           25 :         TyTy::VariantDef *variant
    1075           25 :           = adt->get_variants ().at (ctor.get_variant_index ());
    1076           50 :         buf += "::" + variant->get_identifier ();
    1077              : 
    1078           25 :         switch (variant->get_variant_type ())
    1079              :           {
    1080            5 :           case TyTy::VariantDef::VariantType::UNIT:
    1081            5 :           case TyTy::VariantDef::VariantType::NUM:
    1082            5 :             {
    1083            5 :               return buf;
    1084              :             }
    1085           20 :             break;
    1086           20 :           case TyTy::VariantDef::VariantType::TUPLE:
    1087           20 :             {
    1088           20 :               buf += "(";
    1089           42 :               for (size_t i = 0; i < fields.size (); i++)
    1090              :                 {
    1091            4 :                   buf += fields.at (i).to_string ();
    1092            2 :                   if (i < fields.size () - 1)
    1093            0 :                     buf += ", ";
    1094              :                 }
    1095           20 :               buf += ")";
    1096           20 :               return buf;
    1097              :             }
    1098            0 :             break;
    1099            0 :           case TyTy::VariantDef::VariantType::STRUCT:
    1100            0 :             {
    1101            0 :               buf += " {";
    1102            0 :               if (!fields.empty ())
    1103            0 :                 buf += " ";
    1104              : 
    1105            0 :               for (size_t i = 0; i < fields.size (); i++)
    1106              :                 {
    1107            0 :                   buf += variant->get_fields ().at (i)->get_name () + ": ";
    1108            0 :                   buf += fields.at (i).to_string ();
    1109            0 :                   if (i < fields.size () - 1)
    1110            0 :                     buf += ", ";
    1111              :                 }
    1112              : 
    1113            0 :               if (!fields.empty ())
    1114            0 :                 buf += " ";
    1115              : 
    1116            0 :               buf += "}";
    1117              :             }
    1118            0 :             break;
    1119            0 :           default:
    1120            0 :             {
    1121            0 :               rust_unreachable ();
    1122              :             }
    1123            0 :             break;
    1124              :           }
    1125            0 :         return buf;
    1126           25 :       }
    1127            0 :       break;
    1128            0 :     case Constructor::ConstructorKind::INT_RANGE:
    1129            0 :       {
    1130              :         // TODO: implement
    1131            0 :         rust_unreachable ();
    1132              :       }
    1133            0 :       break;
    1134            0 :     case Constructor::ConstructorKind::WILDCARD:
    1135            0 :       {
    1136            0 :         return "_";
    1137              :       }
    1138            0 :       break;
    1139            0 :     case Constructor::ConstructorKind::REFERENCE:
    1140            0 :       {
    1141              :         // TODO: implement
    1142            0 :         rust_unreachable ();
    1143              :       }
    1144            0 :       break;
    1145            0 :     default:
    1146            0 :       {
    1147            0 :         rust_unreachable ();
    1148              :       }
    1149              :       break;
    1150              :     }
    1151              :   rust_unreachable ();
    1152              : }
    1153              : 
    1154              : void
    1155         2612 : WitnessMatrix::apply_constructor (const Constructor &ctor,
    1156              :                                   const std::set<Constructor> &missings,
    1157              :                                   TyTy::BaseType *ty)
    1158              : {
    1159         2612 :   int arity = 0;
    1160              :   // TODO: only support struct and variant ctor for now.
    1161         2612 :   switch (ctor.get_kind ())
    1162              :     {
    1163              :     case Constructor::ConstructorKind::WILDCARD:
    1164              :       {
    1165              :         arity = 0;
    1166              :       }
    1167              :       break;
    1168         1359 :     case Constructor::ConstructorKind::STRUCT:
    1169         1359 :     case Constructor::ConstructorKind::VARIANT:
    1170         1359 :       {
    1171         1359 :         if (ty->get_kind () == TyTy::TypeKind::ADT)
    1172              :           {
    1173         1359 :             TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1174         1359 :             TyTy::VariantDef *variant
    1175         1359 :               = adt->get_variants ().at (ctor.get_variant_index ());
    1176         1359 :             if (variant->get_variant_type () == TyTy::VariantDef::NUM
    1177         1359 :                 || variant->get_variant_type () == TyTy::VariantDef::UNIT)
    1178              :               arity = 0;
    1179              :             else
    1180          780 :               arity = variant->get_fields ().size ();
    1181              :           }
    1182              :       }
    1183              :       break;
    1184            0 :     default:
    1185            0 :       {
    1186            0 :         rust_unreachable ();
    1187              :       }
    1188              :     }
    1189              : 
    1190         2612 :   std::string buf;
    1191         2623 :   for (auto &stack : patstacks)
    1192              :     {
    1193           11 :       buf += "[";
    1194           18 :       for (auto &pat : stack)
    1195           21 :         buf += pat.to_string () + ", ";
    1196              : 
    1197           11 :       buf += "]\n";
    1198              :     }
    1199         2612 :   rust_debug ("witness pats:\n%s", buf.c_str ());
    1200              : 
    1201         2623 :   for (auto &stack : patstacks)
    1202              :     {
    1203           11 :       std::vector<WitnessPat> subfield;
    1204           16 :       for (int i = 0; i < arity; i++)
    1205              :         {
    1206            5 :           if (stack.empty ())
    1207            0 :             subfield.push_back (WitnessPat::make_wildcard (ty));
    1208              :           else
    1209              :             {
    1210            5 :               subfield.push_back (stack.back ());
    1211            5 :               stack.pop_back ();
    1212              :             }
    1213              :         }
    1214              : 
    1215           11 :       stack.emplace_back (ctor, subfield, ty);
    1216           11 :     }
    1217         2612 : }
    1218              : 
    1219              : void
    1220         2612 : WitnessMatrix::extend (const WitnessMatrix &other)
    1221              : {
    1222         2612 :   patstacks.insert (patstacks.end (), other.patstacks.begin (),
    1223              :                     other.patstacks.end ());
    1224         2612 : }
    1225              : 
    1226              : // forward declarations
    1227              : static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx,
    1228              :                                        HIR::Pattern &pattern,
    1229              :                                        TyTy::BaseType *scrutinee_ty);
    1230              : 
    1231              : static DeconstructedPat
    1232          824 : lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
    1233              :                      HIR::TupleStructPattern &pattern,
    1234              :                      TyTy::VariantDef *variant, Constructor &ctor)
    1235              : {
    1236          824 :   int arity = variant->get_fields ().size ();
    1237          824 :   HIR::TupleStructItems &elems = pattern.get_items ();
    1238              : 
    1239          824 :   std::vector<DeconstructedPat> fields;
    1240          824 :   switch (elems.get_item_type ())
    1241              :     {
    1242          788 :     case HIR::TupleStructItems::ItemType::NO_REST:
    1243          788 :       {
    1244          788 :         HIR::TupleStructItemsNoRest &items_no_rest
    1245              :           = static_cast<HIR::TupleStructItemsNoRest &> (elems);
    1246              : 
    1247          788 :         rust_assert (variant->get_fields ().size ()
    1248              :                      == items_no_rest.get_patterns ().size ());
    1249              : 
    1250         1564 :         for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
    1251              :           {
    1252          776 :             fields.push_back (
    1253         1552 :               lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
    1254          776 :                              variant->get_fields ().at (i)->get_field_type ()));
    1255              :           }
    1256          788 :         return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
    1257              :       }
    1258           36 :       break;
    1259           36 :     case HIR::TupleStructItems::ItemType::HAS_REST:
    1260           36 :       {
    1261           36 :         HIR::TupleStructItemsHasRest &items_has_rest
    1262              :           = static_cast<HIR::TupleStructItemsHasRest &> (elems);
    1263              : 
    1264           36 :         size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
    1265           36 :                               + items_has_rest.get_upper_patterns ().size ();
    1266              : 
    1267           36 :         rust_assert (num_patterns <= variant->num_fields ());
    1268              : 
    1269           36 :         size_t i = 0;
    1270           65 :         for (auto &pattern_member : items_has_rest.get_lower_patterns ())
    1271              :           {
    1272           29 :             fields.push_back (lower_pattern (
    1273           29 :               ctx, *pattern_member,
    1274           29 :               variant->get_fields ().at (i++)->get_field_type ()));
    1275              :           }
    1276          100 :         while (i < variant->num_fields ()
    1277          100 :                      - items_has_rest.get_upper_patterns ().size ())
    1278              :           {
    1279           64 :             fields.push_back (
    1280           64 :               DeconstructedPat::make_wildcard (pattern.get_locus ()));
    1281           64 :             i++;
    1282              :           }
    1283           50 :         for (auto &pattern_member : items_has_rest.get_upper_patterns ())
    1284              :           {
    1285           14 :             fields.push_back (lower_pattern (
    1286           14 :               ctx, *pattern_member,
    1287           14 :               variant->get_fields ().at (i++)->get_field_type ()));
    1288              :           }
    1289           36 :         return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
    1290              :       }
    1291            0 :       break;
    1292            0 :     default:
    1293            0 :       {
    1294            0 :         rust_unreachable ();
    1295              :       }
    1296              :     }
    1297          824 : }
    1298              : 
    1299              : static DeconstructedPat
    1300           93 : lower_struct_pattern (Resolver::TypeCheckContext *ctx,
    1301              :                       HIR::StructPattern &pattern, TyTy::VariantDef *variant,
    1302              :                       Constructor ctor)
    1303              : {
    1304           93 :   int arity = variant->get_fields ().size ();
    1305              : 
    1306              :   // Initialize all field patterns to wildcard.
    1307           93 :   std::vector<DeconstructedPat> fields
    1308          186 :     = std::vector<DeconstructedPat> (arity, DeconstructedPat::make_wildcard (
    1309           93 :                                               pattern.get_locus ()));
    1310              : 
    1311           93 :   std::map<std::string, int> field_map;
    1312          248 :   for (int i = 0; i < arity; i++)
    1313              :     {
    1314          155 :       auto &f = variant->get_fields ().at (i);
    1315          155 :       field_map[f->get_name ()] = i;
    1316              :     }
    1317              : 
    1318              :   // Fill in the fields with the present patterns.
    1319           93 :   HIR::StructPatternElements elems = pattern.get_struct_pattern_elems ();
    1320          245 :   for (auto &elem : elems.get_struct_pattern_fields ())
    1321              :     {
    1322          152 :       switch (elem->get_item_type ())
    1323              :         {
    1324           79 :         case HIR::StructPatternField::ItemType::IDENT:
    1325           79 :           {
    1326           79 :             HIR::StructPatternFieldIdent *ident
    1327           79 :               = static_cast<HIR::StructPatternFieldIdent *> (elem.get ());
    1328           79 :             int field_idx
    1329           79 :               = field_map.at (ident->get_identifier ().as_string ());
    1330           79 :             fields.at (field_idx)
    1331           79 :               = DeconstructedPat::make_wildcard (pattern.get_locus ());
    1332              :           }
    1333           79 :           break;
    1334           55 :         case HIR::StructPatternField::ItemType::IDENT_PAT:
    1335           55 :           {
    1336           55 :             HIR::StructPatternFieldIdentPat *ident_pat
    1337           55 :               = static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ());
    1338           55 :             int field_idx
    1339           55 :               = field_map.at (ident_pat->get_identifier ().as_string ());
    1340           55 :             fields.at (field_idx) = lower_pattern (
    1341              :               ctx, ident_pat->get_pattern (),
    1342          110 :               variant->get_fields ().at (field_idx)->get_field_type ());
    1343              :           }
    1344           55 :           break;
    1345           18 :         case HIR::StructPatternField::ItemType::TUPLE_PAT:
    1346           18 :           {
    1347           18 :             HIR::StructPatternFieldTuplePat *tuple_pat
    1348           18 :               = static_cast<HIR::StructPatternFieldTuplePat *> (elem.get ());
    1349           18 :             int field_idx = tuple_pat->get_index ();
    1350           18 :             fields.at (field_idx) = lower_pattern (
    1351              :               ctx, tuple_pat->get_tuple_pattern (),
    1352           36 :               variant->get_fields ().at (field_idx)->get_field_type ());
    1353              :           }
    1354           18 :           break;
    1355            0 :         default:
    1356            0 :           {
    1357            0 :             rust_unreachable ();
    1358              :           }
    1359              :         }
    1360              :     }
    1361              : 
    1362           93 :   return DeconstructedPat{ctor, arity, fields, pattern.get_locus ()};
    1363           93 : };
    1364              : 
    1365              : static DeconstructedPat
    1366         3389 : lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
    1367              :                TyTy::BaseType *scrutinee_ty)
    1368              : {
    1369         3389 :   HIR::Pattern::PatternType pat_type = pattern.get_pattern_type ();
    1370         3389 :   switch (pat_type)
    1371              :     {
    1372         1073 :     case HIR::Pattern::PatternType::WILDCARD:
    1373         1073 :     case HIR::Pattern::PatternType::IDENTIFIER:
    1374         1073 :       {
    1375         1073 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1376              :       }
    1377          768 :       break;
    1378          768 :     case HIR::Pattern::PatternType::PATH:
    1379          768 :       {
    1380              :         // TODO: support constants, associated constants, enum variants and
    1381              :         // structs
    1382              :         // https://doc.rust-lang.org/reference/patterns.html#path-patterns
    1383              :         // unimplemented. Treat this pattern as wildcard for now.
    1384          768 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1385              :       }
    1386           31 :       break;
    1387           31 :     case HIR::Pattern::PatternType::REFERENCE:
    1388           31 :       {
    1389              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1390           31 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1391              :       }
    1392          917 :       break;
    1393          917 :     case HIR::Pattern::PatternType::STRUCT:
    1394          917 :     case HIR::Pattern::PatternType::TUPLE_STRUCT:
    1395          917 :       {
    1396          917 :         HirId path_id = UNKNOWN_HIRID;
    1397          917 :         if (pat_type == HIR::Pattern::PatternType::STRUCT)
    1398              :           {
    1399           93 :             HIR::StructPattern &struct_pattern
    1400              :               = static_cast<HIR::StructPattern &> (pattern);
    1401           93 :             path_id = struct_pattern.get_path ().get_mappings ().get_hirid ();
    1402              :           }
    1403              :         else
    1404              :           {
    1405          824 :             HIR::TupleStructPattern &tuple_pattern
    1406              :               = static_cast<HIR::TupleStructPattern &> (pattern);
    1407          824 :             path_id = tuple_pattern.get_path ().get_mappings ().get_hirid ();
    1408              :           }
    1409              : 
    1410          917 :         rust_assert (scrutinee_ty->get_kind () == TyTy::TypeKind::ADT);
    1411          917 :         TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (scrutinee_ty);
    1412              : 
    1413          917 :         Constructor ctor = Constructor::make_struct ();
    1414          917 :         TyTy::VariantDef *variant;
    1415          917 :         if (adt->is_struct_struct () || adt->is_tuple_struct ())
    1416           84 :           variant = adt->get_variants ().at (0);
    1417          833 :         else if (adt->is_enum ())
    1418              :           {
    1419          833 :             HirId variant_id = UNKNOWN_HIRID;
    1420          833 :             bool ok = ctx->lookup_variant_definition (path_id, &variant_id);
    1421          833 :             rust_assert (ok);
    1422              : 
    1423          833 :             int variant_idx;
    1424          833 :             ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_idx);
    1425          833 :             rust_assert (ok);
    1426              : 
    1427          833 :             ctor = Constructor::make_variant (variant_idx);
    1428              :           }
    1429              :         else
    1430              :           {
    1431            0 :             rust_unreachable ();
    1432              :           }
    1433          917 :         rust_assert (variant->get_variant_type ()
    1434              :                        == TyTy::VariantDef::VariantType::TUPLE
    1435              :                      || variant->get_variant_type ()
    1436              :                           == TyTy::VariantDef::VariantType::STRUCT);
    1437              : 
    1438          917 :         if (pat_type == HIR::Pattern::PatternType::STRUCT)
    1439              :           {
    1440           93 :             HIR::StructPattern &struct_pattern
    1441              :               = static_cast<HIR::StructPattern &> (pattern);
    1442           93 :             return lower_struct_pattern (ctx, struct_pattern, variant, ctor);
    1443              :           }
    1444              :         else
    1445              :           {
    1446          824 :             HIR::TupleStructPattern &tuple_pattern
    1447              :               = static_cast<HIR::TupleStructPattern &> (pattern);
    1448          824 :             return lower_tuple_pattern (ctx, tuple_pattern, variant, ctor);
    1449              :           }
    1450              :       }
    1451          129 :       break;
    1452          129 :     case HIR::Pattern::PatternType::TUPLE:
    1453          129 :       {
    1454              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1455          129 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1456              :       }
    1457           75 :       break;
    1458           75 :     case HIR::Pattern::PatternType::SLICE:
    1459           75 :       {
    1460              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1461           75 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1462              :       }
    1463          145 :       break;
    1464          145 :     case HIR::Pattern::PatternType::ALT:
    1465          145 :       {
    1466              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1467          145 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1468              :       }
    1469          207 :       break;
    1470          207 :     case HIR::Pattern::PatternType::LITERAL:
    1471          207 :       {
    1472              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1473          207 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1474              :       }
    1475           44 :       break;
    1476           44 :     case HIR::Pattern::PatternType::RANGE:
    1477           44 :       {
    1478              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1479           44 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1480              :       }
    1481            0 :       break;
    1482            0 :     case HIR::Pattern::PatternType::GROUPED:
    1483            0 :       {
    1484              :         // TODO: unimplemented. Treat this pattern as wildcard for now.
    1485            0 :         return DeconstructedPat::make_wildcard (pattern.get_locus ());
    1486              :       }
    1487            0 :       break;
    1488            0 :     default:
    1489            0 :       {
    1490            0 :         rust_unreachable ();
    1491              :       }
    1492              :     }
    1493              : }
    1494              : 
    1495              : static MatchArm
    1496         2497 : lower_arm (Resolver::TypeCheckContext *ctx, HIR::MatchCase &arm,
    1497              :            TyTy::BaseType *scrutinee_ty)
    1498              : {
    1499         2497 :   rust_assert (arm.get_arm ().get_pattern () != nullptr);
    1500              : 
    1501         2497 :   DeconstructedPat pat
    1502         2497 :     = lower_pattern (ctx, *arm.get_arm ().get_pattern (), scrutinee_ty);
    1503         2497 :   return MatchArm (pat, arm.get_arm ().has_match_arm_guard ());
    1504         2497 : }
    1505              : 
    1506              : std::pair<std::set<Constructor>, std::set<Constructor>>
    1507         1930 : split_constructors (std::vector<Constructor> &ctors, PlaceInfo &place_info)
    1508              : {
    1509         1930 :   bool all_wildcard = true;
    1510         6234 :   for (auto &ctor : ctors)
    1511              :     {
    1512         4304 :       if (!ctor.is_wildcard ())
    1513          919 :         all_wildcard = false;
    1514              :     }
    1515              : 
    1516              :   // first pass for the case that all patterns are wildcard
    1517         1930 :   if (all_wildcard)
    1518         2506 :     return std::make_pair (std::set<Constructor> (
    1519         2506 :                              {Constructor::make_wildcard ()}),
    1520         3759 :                            std::set<Constructor> ());
    1521              : 
    1522              :   // TODO: only support enums and structs for now.
    1523          677 :   TyTy::BaseType *ty = place_info.get_type ();
    1524          677 :   rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
    1525          677 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
    1526          677 :   rust_assert (adt->is_enum () || adt->is_struct_struct ()
    1527              :                || adt->is_tuple_struct ());
    1528              : 
    1529          677 :   std::set<Constructor> universe;
    1530          677 :   if (adt->is_enum ())
    1531              :     {
    1532         1926 :       for (size_t i = 0; i < adt->get_variants ().size (); i++)
    1533         1304 :         universe.insert (Constructor::make_variant (i));
    1534              :     }
    1535           55 :   else if (adt->is_struct_struct () || adt->is_tuple_struct ())
    1536              :     {
    1537           55 :       universe.insert (Constructor::make_struct ());
    1538              :     }
    1539              : 
    1540          677 :   std::set<Constructor> present;
    1541         1516 :   for (auto &ctor : ctors)
    1542              :     {
    1543         1437 :       if (ctor.is_wildcard ())
    1544         1196 :         return std::make_pair (universe, std::set<Constructor> ());
    1545              :       else
    1546          839 :         present.insert (ctor);
    1547              :     }
    1548              : 
    1549           79 :   std::set<Constructor> missing;
    1550           79 :   std::set_difference (universe.begin (), universe.end (), present.begin (),
    1551              :                        present.end (), std::inserter (missing, missing.end ()));
    1552          158 :   return std::make_pair (universe, missing);
    1553          756 : }
    1554              : 
    1555              : // The core of the algorithm. It computes the usefulness and exhaustiveness of a
    1556              : // given matrix recursively.
    1557              : // TODO: calculate usefulness
    1558              : static WitnessMatrix
    1559         3693 : compute_exhaustiveness_and_usefulness (Resolver::TypeCheckContext *ctx,
    1560              :                                        Matrix &matrix)
    1561              : {
    1562         3693 :   rust_debug ("call compute_exhaustiveness_and_usefulness");
    1563         3693 :   rust_debug ("matrix: %s", matrix.to_string ().c_str ());
    1564              : 
    1565         3693 :   if (matrix.get_rows ().empty ())
    1566              :     {
    1567              :       // no rows left. This means a non-exhaustive pattern.
    1568            6 :       rust_debug ("non-exhaustive subpattern found");
    1569            6 :       return WitnessMatrix::make_unit ();
    1570              :     }
    1571              : 
    1572              :   // Base case: there are no columns in matrix.
    1573         3687 :   if (matrix.get_place_infos ().empty ())
    1574         1757 :     return WitnessMatrix::make_empty ();
    1575              : 
    1576         1930 :   std::vector<Constructor> heads;
    1577         6234 :   for (auto head : matrix.heads ())
    1578        10538 :     heads.push_back (head.ctor ());
    1579              : 
    1580              :   // TODO: not sure missing ctors need to be calculated
    1581         1930 :   auto ctors_and_missings
    1582         1930 :     = split_constructors (heads, matrix.get_place_infos ().at (0));
    1583         1930 :   std::set<Constructor> ctors = ctors_and_missings.first;
    1584         1930 :   std::set<Constructor> missings = ctors_and_missings.second;
    1585              : 
    1586         1930 :   WitnessMatrix ret = WitnessMatrix::make_empty ();
    1587         4542 :   for (auto &ctor : ctors)
    1588              :     {
    1589         2612 :       rust_debug ("specialize with %s", ctor.to_string ().c_str ());
    1590              :       // TODO: Instead of creating new matrix, we can change the original matrix
    1591              :       // and use it for sub-pattern matching. It will significantly reduce
    1592              :       // memory usage.
    1593         2612 :       Matrix spec_matrix = matrix.specialize (ctor);
    1594              : 
    1595         2612 :       WitnessMatrix witness
    1596         2612 :         = compute_exhaustiveness_and_usefulness (ctx, spec_matrix);
    1597              : 
    1598         2612 :       TyTy::BaseType *ty = matrix.get_place_infos ().at (0).get_type ();
    1599         2612 :       witness.apply_constructor (ctor, missings, ty);
    1600         2612 :       ret.extend (witness);
    1601         5224 :     }
    1602              : 
    1603         1930 :   return ret;
    1604         1930 : }
    1605              : 
    1606              : static void
    1607         1081 : emit_exhaustiveness_error (Resolver::TypeCheckContext *ctx,
    1608              :                            HIR::MatchExpr &expr, WitnessMatrix &witness)
    1609              : {
    1610         1081 :   TyTy::BaseType *scrutinee_ty;
    1611         1081 :   bool ok
    1612         1081 :     = ctx->lookup_type (expr.get_scrutinee_expr ().get_mappings ().get_hirid (),
    1613              :                         &scrutinee_ty);
    1614         1081 :   rust_assert (ok);
    1615              : 
    1616         1081 :   if (!witness.empty ())
    1617              :     {
    1618            4 :       std::stringstream buf;
    1619           14 :       for (size_t i = 0; i < witness.get_stacks ().size (); i++)
    1620              :         {
    1621            6 :           auto &stack = witness.get_stacks ().at (i);
    1622            6 :           WitnessPat w = WitnessPat::make_wildcard (scrutinee_ty);
    1623            6 :           if (!stack.empty ())
    1624            6 :             w = stack.at (0);
    1625              : 
    1626            6 :           rust_debug ("Witness[%d]: %s", (int) i, w.to_string ().c_str ());
    1627           12 :           buf << "'" << w.to_string () << "'";
    1628            6 :           if (i != witness.get_stacks ().size () - 1)
    1629            2 :             buf << " and ";
    1630            6 :         }
    1631            4 :       rust_error_at (expr.get_scrutinee_expr ().get_locus (),
    1632              :                      "non-exhaustive patterns: %s not covered",
    1633            4 :                      buf.str ().c_str ());
    1634            4 :     }
    1635              :   else
    1636              :     {
    1637         1077 :       rust_debug ("no witness found");
    1638              :     }
    1639         1081 : }
    1640              : 
    1641              : // Entry point for computing match usefulness and check exhaustiveness
    1642              : void
    1643         1086 : check_match_usefulness (Resolver::TypeCheckContext *ctx,
    1644              :                         TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr)
    1645              : {
    1646         1086 :   if (!expr.has_match_arms ())
    1647            5 :     return;
    1648              : 
    1649              :   // Lower the arms to a more convenient representation.
    1650         1081 :   std::vector<MatrixRow> rows;
    1651         3578 :   for (auto &arm : expr.get_match_cases ())
    1652              :     {
    1653         2497 :       PatStack pats;
    1654         2497 :       MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty);
    1655         2497 :       PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ());
    1656         2497 :       pats.push (pat);
    1657         2497 :       rows.emplace_back (pats, lowered.has_guard ());
    1658         2497 :     }
    1659              : 
    1660         1081 :   std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}};
    1661         2162 :   Matrix matrix{rows, place_infos};
    1662              : 
    1663         1081 :   WitnessMatrix witness = compute_exhaustiveness_and_usefulness (ctx, matrix);
    1664              : 
    1665         1081 :   emit_exhaustiveness_error (ctx, expr, witness);
    1666         2162 : }
    1667              : 
    1668              : } // namespace Analysis
    1669              : } // 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.