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