https://gcc.gnu.org/g:5fe9110bbf425f3a41f02ca191e5a34d34520712

commit 5fe9110bbf425f3a41f02ca191e5a34d34520712
Author: Marc Poulhiès <d...@kataplop.net>
Date:   Wed Jun 12 21:58:26 2024 +0200

    rust: Desugar IfLet* into MatchExpr
    
    Replace the "regular" AST->HIR lowering for IfLet* with a desugaring
    into a MatchExpr.
    
    Desugar a simple if let:
    
       if let Some(y) = some_value {
         bar();
       }
    
    into:
    
       match some_value {
         Some(y) => {bar();},
         _ => ()
       }
    
    Same applies for IfLetExprConseqElse (if let with an else block).
    
    Desugar:
    
       if let Some(y) = some_value {
         bar();
       } else {
         baz();
       }
    
    into:
    
       match some_value {
         Some(y) => {bar();},
         _ => {baz();}
       }
    
    Fixes https://github.com/Rust-GCC/gccrs/issues/1177
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-block.h: Adjust after removal of
            HIR::IfLetExpr and HIR::IfLetExprConseqElse.
            * backend/rust-compile-expr.h: Likewise.
            * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
            (ExprStmtBuilder::visit): Likewise.
            * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise.
            * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h:
            Likewise.
            * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
            * checks/errors/borrowck/rust-function-collector.h: Likewise.
            * checks/errors/privacy/rust-privacy-reporter.cc
            (PrivacyReporter::visit): Likewise.
            * checks/errors/privacy/rust-privacy-reporter.h: Likewise.
            * checks/errors/rust-const-checker.cc (ConstChecker::visit):
            Likewise.
            * checks/errors/rust-const-checker.h: Likewise.
            * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit):
            Likewise.
            * checks/errors/rust-unsafe-checker.h: Likewise.
            * hir/rust-ast-lower-block.h (ASTLoweringIfLetBlock::translate):
            Change return type.
            * hir/rust-ast-lower.cc (ASTLoweringIfLetBlock::desugar_iflet):
            New.
            (ASTLoweringIfLetBlock::visit(AST::IfLetExpr &)): Adjust and use
            desugar_iflet.
            * hir/rust-ast-lower.h: Add comment.
            * hir/rust-hir-dump.cc (Dump::do_ifletexpr): Remove.
            (Dump::visit(IfLetExpr&)): Remove.
            (Dump::visit(IfLetExprConseqElse&)): Remove.
            * hir/rust-hir-dump.h (Dump::do_ifletexpr): Remove.
            (Dump::visit(IfLetExpr&)): Remove.
            (Dump::visit(IfLetExprConseqElse&)): Remove.
            * hir/tree/rust-hir-expr.h (class IfLetExpr): Remove.
            (class IfLetExprConseqElse): Remove.
            * hir/tree/rust-hir-full-decls.h (class IfLetExpr): Remove.
            (class IfLetExprConseqElse): Remove.
            * hir/tree/rust-hir-visitor.h: Adjust after removal of
            HIR::IfLetExpr and HIR::IfLetExprConseqElse.
            * hir/tree/rust-hir.cc (IfLetExpr::as_string): Remove.
            (IfLetExprConseqElse::as_string): Remove.
            (IfLetExpr::accept_vis): Remove.
            (IfLetExprConseqElse::accept_vis): Remove.
            * hir/tree/rust-hir.h: Adjust after removal of HIR::IfLetExpr and
            HIR::IfLetExprConseqElse.
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
            Likewise.
            * typecheck/rust-hir-type-check-expr.h: Likewise.
            * checks/errors/rust-hir-pattern-analysis.cc
            (PatternChecker::visit (IfLetExpr &)): Remove.
            (PatternChecker::visit (IfLetExprConseqElse &)): Remove.
            * checks/errors/rust-hir-pattern-analysis.h (visit(IfLetExpr &)): 
Remove.
            (visit(IfLetExprConseqElse &)): Remove.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/if_let_expr.rs: Adjust.
            * rust/compile/if_let_expr_simple.rs: New test.
            * rust/compile/iflet.rs: New test.
            * rust/execute/torture/iflet.rs: New test.
            * rust/compile/nr2/exclude: Add iflet.rs and if_let_expr_simple.rs
    
    Signed-off-by: Marc Poulhiès <d...@kataplop.net>

Diff:
---
 gcc/rust/backend/rust-compile-block.h              |   4 -
 gcc/rust/backend/rust-compile-expr.h               |   2 -
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  |  12 --
 .../errors/borrowck/rust-bir-builder-expr-stmt.h   |   2 -
 .../borrowck/rust-bir-builder-lazyboolexpr.h       |   8 -
 .../errors/borrowck/rust-bir-builder-struct.h      |   2 -
 .../errors/borrowck/rust-function-collector.h      |   2 -
 .../checks/errors/privacy/rust-privacy-reporter.cc |  15 --
 .../checks/errors/privacy/rust-privacy-reporter.h  |   2 -
 gcc/rust/checks/errors/rust-const-checker.cc       |  16 --
 gcc/rust/checks/errors/rust-const-checker.h        |   2 -
 .../checks/errors/rust-hir-pattern-analysis.cc     |  16 --
 gcc/rust/checks/errors/rust-hir-pattern-analysis.h |   2 -
 gcc/rust/checks/errors/rust-unsafe-checker.cc      |  16 --
 gcc/rust/checks/errors/rust-unsafe-checker.h       |   2 -
 gcc/rust/hir/rust-ast-lower-block.h                |  11 +-
 gcc/rust/hir/rust-ast-lower.cc                     | 144 +++++++++++++----
 gcc/rust/hir/rust-ast-lower.h                      |   5 +
 gcc/rust/hir/rust-hir-dump.cc                      |  28 ----
 gcc/rust/hir/rust-hir-dump.h                       |   3 -
 gcc/rust/hir/tree/rust-hir-expr.h                  | 176 +--------------------
 gcc/rust/hir/tree/rust-hir-full-decls.h            |   2 -
 gcc/rust/hir/tree/rust-hir-visitor.h               |   6 -
 gcc/rust/hir/tree/rust-hir.cc                      |  59 -------
 gcc/rust/hir/tree/rust-hir.h                       |   1 -
 gcc/rust/typecheck/rust-hir-type-check-expr.cc     |  61 -------
 gcc/rust/typecheck/rust-hir-type-check-expr.h      |   2 -
 gcc/testsuite/rust/compile/if_let_expr.rs          |   5 +-
 gcc/testsuite/rust/compile/if_let_expr_simple.rs   |  12 ++
 gcc/testsuite/rust/compile/iflet.rs                |  32 ++++
 gcc/testsuite/rust/compile/nr2/exclude             |   3 +
 gcc/testsuite/rust/execute/torture/iflet.rs        |  84 ++++++++++
 32 files changed, 260 insertions(+), 477 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-block.h 
b/gcc/rust/backend/rust-compile-block.h
index 112f7b07e5e6..46a32cfaf867 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -96,8 +96,6 @@ public:
   void visit (HIR::LoopExpr &) override {}
   void visit (HIR::WhileLoopExpr &) override {}
   void visit (HIR::WhileLetLoopExpr &) override {}
-  void visit (HIR::IfLetExpr &) override {}
-  void visit (HIR::IfLetExprConseqElse &) override {}
   void visit (HIR::MatchExpr &) override {}
   void visit (HIR::AwaitExpr &) override {}
   void visit (HIR::AsyncBlockExpr &) override {}
@@ -180,8 +178,6 @@ public:
   void visit (HIR::LoopExpr &) override {}
   void visit (HIR::WhileLoopExpr &) override {}
   void visit (HIR::WhileLetLoopExpr &) override {}
-  void visit (HIR::IfLetExpr &) override {}
-  void visit (HIR::IfLetExprConseqElse &) override {}
   void visit (HIR::MatchExpr &) override {}
   void visit (HIR::AwaitExpr &) override {}
   void visit (HIR::AsyncBlockExpr &) override {}
diff --git a/gcc/rust/backend/rust-compile-expr.h 
b/gcc/rust/backend/rust-compile-expr.h
index 8f187029a109..871111bb007c 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -77,8 +77,6 @@ public:
   // TODO
   // these need to be sugared in the HIR to if statements and a match
   void visit (HIR::WhileLetLoopExpr &) override {}
-  void visit (HIR::IfLetExpr &) override {}
-  void visit (HIR::IfLetExprConseqElse &) override {}
 
   // lets not worry about async yet....
   void visit (HIR::AwaitExpr &) override {}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index c11cff0ae4df..3ae58843f1fb 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -611,18 +611,6 @@ ExprStmtBuilder::visit (HIR::IfExprConseqElse &expr)
     add_jump (else_end_bb, final_start_bb);
 }
 
-void
-ExprStmtBuilder::visit (HIR::IfLetExpr &expr)
-{
-  rust_sorry_at (expr.get_locus (), "if let expressions are not supported");
-}
-
-void
-ExprStmtBuilder::visit (HIR::IfLetExprConseqElse &expr)
-{
-  rust_sorry_at (expr.get_locus (), "if let expressions are not supported");
-}
-
 void
 ExprStmtBuilder::visit (HIR::MatchExpr &expr)
 {
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
index d67d86fca78a..f538a1209a8f 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
@@ -101,8 +101,6 @@ protected: // Expr
   void visit (HIR::IfExprConseqElse &expr) override;
   void visit (HIR::InlineAsm &expr) override;
 
-  void visit (HIR::IfLetExpr &expr) override;
-  void visit (HIR::IfLetExprConseqElse &expr) override;
   void visit (HIR::MatchExpr &expr) override;
   void visit (HIR::AwaitExpr &expr) override;
   void visit (HIR::AsyncBlockExpr &expr) override;
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
index 3a27c8e3337c..926ba692e2ca 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -193,14 +193,6 @@ public:
   {
     return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
   }
-  void visit (HIR::IfLetExpr &expr) override
-  {
-    return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
-  }
-  void visit (HIR::IfLetExprConseqElse &expr) override
-  {
-    return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
-  }
   void visit (HIR::MatchExpr &expr) override
   {
     return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index 787b7017e1b6..351b4c8a3758 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -149,8 +149,6 @@ protected:
   void visit (HIR::WhileLetLoopExpr &expr) override { rust_unreachable (); }
   void visit (HIR::IfExpr &expr) override { rust_unreachable (); }
   void visit (HIR::IfExprConseqElse &expr) override { rust_unreachable (); }
-  void visit (HIR::IfLetExpr &expr) override { rust_unreachable (); }
-  void visit (HIR::IfLetExprConseqElse &expr) override { rust_unreachable (); }
   void visit (HIR::MatchExpr &expr) override { rust_unreachable (); }
   void visit (HIR::AwaitExpr &expr) override { rust_unreachable (); }
   void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); }
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h 
b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index 725d312f1113..1f7cf48e412b 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -119,8 +119,6 @@ public:
   void visit (HIR::WhileLetLoopExpr &expr) override {}
   void visit (HIR::IfExpr &expr) override {}
   void visit (HIR::IfExprConseqElse &expr) override {}
-  void visit (HIR::IfLetExpr &expr) override {}
-  void visit (HIR::IfLetExprConseqElse &expr) override {}
   void visit (HIR::MatchExpr &expr) override {}
   void visit (HIR::AwaitExpr &expr) override {}
   void visit (HIR::AsyncBlockExpr &expr) override {}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 43eb115a6325..9e4b0073db46 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -594,21 +594,6 @@ PrivacyReporter::visit (HIR::IfExprConseqElse &expr)
   expr.get_else_block ()->accept_vis (*this);
 }
 
-void
-PrivacyReporter::visit (HIR::IfLetExpr &)
-{
-  // TODO: We need to visit the if_let_expr
-  // TODO: We need to visit the block as well
-}
-
-void
-PrivacyReporter::visit (HIR::IfLetExprConseqElse &)
-{
-  // TODO: We need to visit the if_let_expr
-  // TODO: We need to visit the if_block as well
-  // TODO: We need to visit the else_block as well
-}
-
 void
 PrivacyReporter::visit (HIR::MatchExpr &expr)
 {
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index c00ab37a78f8..f90f5a2fc8ba 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -121,8 +121,6 @@ types
   virtual void visit (HIR::WhileLetLoopExpr &expr);
   virtual void visit (HIR::IfExpr &expr);
   virtual void visit (HIR::IfExprConseqElse &expr);
-  virtual void visit (HIR::IfLetExpr &expr);
-  virtual void visit (HIR::IfLetExprConseqElse &expr);
   virtual void visit (HIR::MatchExpr &expr);
   virtual void visit (HIR::AwaitExpr &expr);
   virtual void visit (HIR::AsyncBlockExpr &expr);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc 
b/gcc/rust/checks/errors/rust-const-checker.cc
index d3c25b566b90..f858a2233495 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -511,22 +511,6 @@ ConstChecker::visit (IfExprConseqElse &expr)
   expr.get_else_block ()->accept_vis (*this);
 }
 
-void
-ConstChecker::visit (IfLetExpr &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-ConstChecker::visit (IfLetExprConseqElse &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-
-  // TODO: Visit else expression
-}
-
 void
 ConstChecker::visit (MatchExpr &expr)
 {
diff --git a/gcc/rust/checks/errors/rust-const-checker.h 
b/gcc/rust/checks/errors/rust-const-checker.h
index 2bbf67b20d70..5363df9d5b1c 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -128,8 +128,6 @@ private:
   virtual void visit (WhileLetLoopExpr &expr) override;
   virtual void visit (IfExpr &expr) override;
   virtual void visit (IfExprConseqElse &expr) override;
-  virtual void visit (IfLetExpr &expr) override;
-  virtual void visit (IfLetExprConseqElse &expr) override;
   virtual void visit (MatchExpr &expr) override;
   virtual void visit (AwaitExpr &expr) override;
   virtual void visit (AsyncBlockExpr &expr) override;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index f46f429e9306..8fb795b7b837 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -389,22 +389,6 @@ PatternChecker::visit (IfExprConseqElse &expr)
   expr.get_else_block ()->accept_vis (*this);
 }
 
-void
-PatternChecker::visit (IfLetExpr &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-PatternChecker::visit (IfLetExprConseqElse &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-
-  expr.get_else_block ()->accept_vis (*this);
-}
-
 void
 PatternChecker::visit (MatchExpr &expr)
 {
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 1af02baa24b1..9c43d4143d2a 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -102,8 +102,6 @@ private:
   virtual void visit (WhileLetLoopExpr &expr) override;
   virtual void visit (IfExpr &expr) override;
   virtual void visit (IfExprConseqElse &expr) override;
-  virtual void visit (IfLetExpr &expr) override;
-  virtual void visit (IfLetExprConseqElse &expr) override;
   virtual void visit (HIR::MatchExpr &expr) override;
   virtual void visit (AwaitExpr &expr) override;
   virtual void visit (AsyncBlockExpr &expr) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc 
b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 3bf72428aadb..667e5257b86b 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -633,22 +633,6 @@ UnsafeChecker::visit (IfExprConseqElse &expr)
   expr.get_else_block ()->accept_vis (*this);
 }
 
-void
-UnsafeChecker::visit (IfLetExpr &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-UnsafeChecker::visit (IfLetExprConseqElse &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-
-  // TODO: Visit else expression
-}
-
 void
 UnsafeChecker::visit (MatchExpr &expr)
 {
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h 
b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 3a1e715d2442..bd88dc395ea0 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -110,8 +110,6 @@ private:
   virtual void visit (WhileLetLoopExpr &expr) override;
   virtual void visit (IfExpr &expr) override;
   virtual void visit (IfExprConseqElse &expr) override;
-  virtual void visit (IfLetExpr &expr) override;
-  virtual void visit (IfLetExprConseqElse &expr) override;
   virtual void visit (MatchExpr &expr) override;
   virtual void visit (AwaitExpr &expr) override;
   virtual void visit (AsyncBlockExpr &expr) override;
diff --git a/gcc/rust/hir/rust-ast-lower-block.h 
b/gcc/rust/hir/rust-ast-lower-block.h
index f24173e55985..55541a5ad684 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -115,7 +115,7 @@ class ASTLoweringIfLetBlock : public ASTLoweringBase
   using Rust::HIR::ASTLoweringBase::visit;
 
 public:
-  static HIR::IfLetExpr *translate (AST::IfLetExpr &expr)
+  static HIR::MatchExpr *translate (AST::IfLetExpr &expr)
   {
     ASTLoweringIfLetBlock resolver;
     expr.accept_vis (resolver);
@@ -135,7 +135,10 @@ public:
 private:
   ASTLoweringIfLetBlock () : ASTLoweringBase (), translated (nullptr) {}
 
-  HIR::IfLetExpr *translated;
+  void desugar_iflet (AST::IfLetExpr &, HIR::Expr **, HIR::Expr *,
+                     std::vector<HIR::MatchCase> &);
+
+  HIR::MatchExpr *translated;
 };
 
 class ASTLoweringExprWithBlock : public ASTLoweringBase
@@ -149,9 +152,7 @@ public:
     ASTLoweringExprWithBlock resolver;
     expr.accept_vis (resolver);
     if (resolver.translated != nullptr)
-      {
-       resolver.mappings.insert_hir_expr (resolver.translated);
-      }
+      resolver.mappings.insert_hir_expr (resolver.translated);
 
     *terminated = resolver.terminated;
     return resolver.translated;
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 940da204cc5b..c92c9432a68e 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -24,6 +24,8 @@
 #include "rust-ast-lower-type.h"
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-struct-field-expr.h"
+#include "rust-expr.h"
+#include "rust-hir-expr.h"
 
 namespace Rust {
 namespace HIR {
@@ -198,62 +200,144 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqElse &expr)
     std::unique_ptr<HIR::ExprWithBlock> (else_block), expr.get_locus ());
 }
 
+/**
+ *  Lowers the common part "if let 'pattern' = 'expr' { 'if_block' }" of
+ *  IfLetExpr[ConseqElse]:
+ *  - 'expr' is lowered into *BRANCH_VALUE
+ *  - 'pattern' + 'if_block' are lowered and resulting ARM pushed in MATCH_ARMS
+ *  - 'KASE_ELSE_EXPR' is the lowered HIR to be used in the else part.
+ *
+ *  Looks like:
+ *
+ *  match (expr) {
+ *    pattern => {if_block}
+ *    _ => kase_else_expr
+ *  }
+ *
+ */
 void
-ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr)
+ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
+                                     HIR::Expr **branch_value,
+                                     HIR::Expr *kase_else_expr,
+                                     std::vector<HIR::MatchCase> &match_arms)
 {
-  std::vector<std::unique_ptr<HIR::Pattern>> patterns;
+  HIR::Expr *kase_expr;
+  std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns;
+
+  *branch_value = ASTLoweringExpr::translate (expr.get_value_expr ());
+  kase_expr = ASTLoweringExpr::translate (expr.get_if_block ());
+
+  // (stable) if let only accepts a single pattern, but (unstable) if let 
chains
+  // need more than one pattern.
+  // We don't support if let chains, so only support a single pattern.
+  rust_assert (expr.get_patterns ().size () == 1);
+
   for (auto &pattern : expr.get_patterns ())
     {
       HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
-      patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
+      match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
     }
-  HIR::Expr *value_ptr = ASTLoweringExpr::translate (expr.get_value_expr ());
 
-  bool ignored_terminated = false;
-  HIR::BlockExpr *block
-    = ASTLoweringBlock::translate (expr.get_if_block (), &ignored_terminated);
+  // The match arm corresponding to the if let pattern when it matches.
+  HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), 
nullptr,
+                    {});
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
                                 mappings.get_next_hir_id (crate_num),
                                 UNKNOWN_LOCAL_DEFID);
 
-  translated = new HIR::IfLetExpr (mapping, std::move (patterns),
-                                  std::unique_ptr<HIR::Expr> (value_ptr),
-                                  std::unique_ptr<HIR::BlockExpr> (block),
-                                  expr.get_locus ());
+  HIR::MatchCase kase (std::move (mapping), std::move (arm),
+                      std::unique_ptr<HIR::Expr> (kase_expr));
+  match_arms.push_back (std::move (kase));
+
+  // The default match arm when the if let pattern does not match
+  std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns_wildcard;
+  Analysis::NodeMapping mapping_default (crate_num, expr.get_node_id (),
+                                        mappings.get_next_hir_id (crate_num),
+                                        UNKNOWN_LOCAL_DEFID);
+
+  std::unique_ptr<HIR::WildcardPattern> wc
+    = std::unique_ptr<HIR::WildcardPattern> (
+      new HIR::WildcardPattern (mapping_default, expr.get_locus ()));
+
+  match_arm_patterns_wildcard.push_back (std::move (wc));
+
+  HIR::MatchArm arm_default (std::move (match_arm_patterns_wildcard),
+                            expr.get_locus (), nullptr, {});
+
+  HIR::MatchCase kase_else (std::move (mapping_default),
+                           std::move (arm_default),
+                           std::unique_ptr<HIR::Expr> (kase_else_expr));
+  match_arms.push_back (std::move (kase_else));
 }
 
 void
-ASTLoweringIfLetBlock::visit (AST::IfLetExprConseqElse &expr)
+ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr)
 {
-  std::vector<std::unique_ptr<HIR::Pattern>> patterns;
-  for (auto &pattern : expr.get_patterns ())
-    {
-      HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
-      patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
-    }
-  HIR::Expr *value_ptr = ASTLoweringExpr::translate (expr.get_value_expr ());
+  // Desugar:
+  //   if let Some(y) = some_value {
+  //     bar();
+  //   }
+  //
+  //   into:
+  //
+  //   match some_value {
+  //     Some(y) => {bar();},
+  //     _ => ()
+  //   }
+
+  HIR::Expr *branch_value;
 
-  bool ignored_terminated = false;
-  HIR::BlockExpr *block
-    = ASTLoweringBlock::translate (expr.get_if_block (), &ignored_terminated);
+  std::vector<HIR::MatchCase> match_arms;
+  auto crate_num = mappings.get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+                                mappings.get_next_hir_id (crate_num),
+                                UNKNOWN_LOCAL_DEFID);
 
-  HIR::ExprWithBlock *else_block
-    = ASTLoweringExprWithBlock::translate (expr.get_else_block (),
-                                          &ignored_terminated);
+  HIR::TupleExpr *unit
+    = new HIR::TupleExpr (mapping, {}, {}, {}, expr.get_locus ());
+
+  desugar_iflet (expr, &branch_value, unit, match_arms);
 
-  rust_assert (else_block);
+  translated
+    = new HIR::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
+                         std::move (match_arms), {}, {}, expr.get_locus ());
+}
+
+void
+ASTLoweringIfLetBlock::visit (AST::IfLetExprConseqElse &expr)
+{
+  // desugar:
+  //   if let Some(y) = some_value {
+  //     bar();
+  //   } else {
+  //     baz();
+  //   }
+  //
+  //   into
+  //   match some_value {
+  //     Some(y) => {bar();},
+  //     _ => {baz();}
+  //   }
+  //
+
+  HIR::Expr *branch_value;
+  std::vector<HIR::MatchCase> match_arms;
+
+  HIR::Expr *kase_else_expr
+    = ASTLoweringExpr::translate (expr.get_else_block ());
+
+  desugar_iflet (expr, &branch_value, kase_else_expr, match_arms);
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
                                 mappings.get_next_hir_id (crate_num),
                                 UNKNOWN_LOCAL_DEFID);
 
-  translated = new HIR::IfLetExprConseqElse (
-    mapping, std::move (patterns), std::unique_ptr<HIR::Expr> (value_ptr),
-    std::unique_ptr<HIR::BlockExpr> (block),
-    std::unique_ptr<HIR::ExprWithBlock> (else_block), expr.get_locus ());
+  translated
+    = new HIR::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
+                         std::move (match_arms), {}, {}, expr.get_locus ());
 }
 
 // rust-ast-lower-struct-field-expr.h
diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h
index 23730e00221c..5ad3e63c824d 100644
--- a/gcc/rust/hir/rust-ast-lower.h
+++ b/gcc/rust/hir/rust-ast-lower.h
@@ -39,6 +39,11 @@ struct_field_name_exists (std::vector<HIR::StructField> 
&fields,
 Visibility
 translate_visibility (const AST::Visibility &vis);
 
+/**
+ * Main base class used for lowering AST to HIR.
+ *
+ * Every subclass should provide a translate() method that takes an AST node 
and
+ * lowers it to some HIR stored in the TRANSLATED member. */
 class ASTLowering
 {
 public:
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 6d750dc1c589..8ebdd3de6251 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -463,17 +463,6 @@ Dump::do_baseloopexpr (BaseLoopExpr &e)
   visit_field ("loop_block", e.get_loop_block ());
 }
 
-void
-Dump::do_ifletexpr (IfLetExpr &e)
-{
-  do_expr (e);
-
-  visit_collection ("match_arm_patterns", e.get_patterns ());
-
-  visit_field ("value", e.get_scrutinee_expr ());
-  visit_field ("if_block", e.get_if_block ());
-}
-
 void
 Dump::do_struct (Struct &e)
 {
@@ -1441,23 +1430,6 @@ Dump::visit (IfExprConseqElse &e)
   end ("IfExprConseqElse");
 }
 
-void
-Dump::visit (IfLetExpr &e)
-{
-  begin ("IfLetExpr");
-  do_ifletexpr (e);
-  end ("IfLetExpr");
-}
-
-void
-Dump::visit (IfLetExprConseqElse &e)
-{
-  begin ("IfLetExprConseqElse");
-  do_ifletexpr (e);
-  visit_field ("else_block", e.get_else_block ());
-  end ("IfLetExprConseqElse");
-}
-
 void
 Dump::visit (MatchExpr &e)
 {
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 2fe0261a363f..920b1031a71d 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -80,7 +80,6 @@ private:
   void do_type (Type &);
   void do_expr (Expr &);
   void do_ifexpr (IfExpr &);
-  void do_ifletexpr (IfLetExpr &);
   void do_pathexpr (PathExpr &);
   void do_pathpattern (PathPattern &);
   void do_genericargs (GenericArgs &);
@@ -162,8 +161,6 @@ private:
   virtual void visit (WhileLetLoopExpr &) override;
   virtual void visit (IfExpr &) override;
   virtual void visit (IfExprConseqElse &) override;
-  virtual void visit (IfLetExpr &) override;
-  virtual void visit (IfLetExprConseqElse &) override;
 
   virtual void visit (MatchExpr &) override;
   virtual void visit (AwaitExpr &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h 
b/gcc/rust/hir/tree/rust-hir-expr.h
index 56cb7d8b6e4a..99044905de37 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -32,7 +32,7 @@ namespace HIR {
 // TODO: inline?
 class LoopLabel /*: public Node*/
 {
-  Lifetime label; // or type LIFETIME_OR_LABEL
+  Lifetime label; // of type LIFETIME_OR_LABEL
 
   location_t locus;
 
@@ -3108,9 +3108,6 @@ protected:
   }
 };
 
-// forward decl for IfExpr
-class IfLetExpr;
-
 // Base if expression with no "else" or "if let" HIR node
 class IfExpr : public ExprWithBlock
 {
@@ -3258,177 +3255,6 @@ protected:
   }
 };
 
-// Basic "if let" expression HIR node with no else
-class IfLetExpr : public ExprWithBlock
-{
-  // MatchArmPatterns patterns;
-  std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
-  std::unique_ptr<Expr> value;
-  std::unique_ptr<BlockExpr> if_block;
-
-  location_t locus;
-
-public:
-  std::string as_string () const override;
-
-  IfLetExpr (Analysis::NodeMapping mappings,
-            std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
-            std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
-            location_t locus)
-    : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
-      match_arm_patterns (std::move (match_arm_patterns)),
-      value (std::move (value)), if_block (std::move (if_block)), locus (locus)
-  {}
-  // outer attributes not allowed on if let exprs either
-
-  // copy constructor with clone
-  IfLetExpr (IfLetExpr const &other)
-    : ExprWithBlock (other),
-      /*match_arm_patterns(other.match_arm_patterns),*/ value (
-       other.value->clone_expr ()),
-      if_block (other.if_block->clone_block_expr ()), locus (other.locus)
-  {
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-  }
-
-  // overload assignment operator to clone
-  IfLetExpr &operator= (IfLetExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    // match_arm_patterns = other.match_arm_patterns;
-    value = other.value->clone_expr ();
-    if_block = other.if_block->clone_block_expr ();
-    locus = other.locus;
-
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
-
-  // move constructors
-  IfLetExpr (IfLetExpr &&other) = default;
-  IfLetExpr &operator= (IfLetExpr &&other) = default;
-
-  // Unique pointer custom clone function
-  std::unique_ptr<IfLetExpr> clone_if_let_expr () const
-  {
-    return std::unique_ptr<IfLetExpr> (clone_if_let_expr_impl ());
-  }
-
-  location_t get_locus () const override final { return locus; }
-
-  void accept_vis (HIRFullVisitor &vis) override;
-  void accept_vis (HIRExpressionVisitor &vis) override;
-
-  std::unique_ptr<Expr> &get_scrutinee_expr () { return value; }
-
-  std::vector<std::unique_ptr<Pattern> > &get_patterns ()
-  {
-    return match_arm_patterns;
-  }
-
-  std::unique_ptr<BlockExpr> &get_if_block () { return if_block; }
-
-  ExprType get_expression_type () const final override
-  {
-    return ExprType::IfLet;
-  }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); 
}
-
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  IfLetExpr *clone_expr_with_block_impl () const override
-  {
-    return new IfLetExpr (*this);
-  }
-
-  // Base clone function but still concrete as concrete base class
-  virtual IfLetExpr *clone_if_let_expr_impl () const
-  {
-    return new IfLetExpr (*this);
-  }
-};
-
-/* HIR node representing "if let" expression with an "else" expression at the
- * end */
-class IfLetExprConseqElse : public IfLetExpr
-{
-  std::unique_ptr<ExprWithBlock> else_block;
-
-public:
-  std::string as_string () const override;
-
-  IfLetExprConseqElse (
-    Analysis::NodeMapping mappings,
-    std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
-    std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
-    std::unique_ptr<ExprWithBlock> else_block, location_t locus)
-    : IfLetExpr (std::move (mappings), std::move (match_arm_patterns),
-                std::move (value), std::move (if_block), locus),
-      else_block (std::move (else_block))
-  {}
-  // outer attributes not allowed
-
-  // copy constructor with clone
-  IfLetExprConseqElse (IfLetExprConseqElse const &other)
-    : IfLetExpr (other), else_block (other.else_block->clone_expr_with_block 
())
-  {}
-
-  // overload assignment operator to clone
-  IfLetExprConseqElse &operator= (IfLetExprConseqElse const &other)
-  {
-    IfLetExpr::operator= (other);
-    // match_arm_patterns = other.match_arm_patterns;
-    // value = other.value->clone_expr();
-    // if_block = other.if_block->clone_block_expr();
-    else_block = other.else_block->clone_expr_with_block ();
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
-
-  // move constructors
-  IfLetExprConseqElse (IfLetExprConseqElse &&other) = default;
-  IfLetExprConseqElse &operator= (IfLetExprConseqElse &&other) = default;
-
-  void accept_vis (HIRFullVisitor &vis) override;
-  void accept_vis (HIRExpressionVisitor &vis) override;
-
-  void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); }
-
-  std::unique_ptr<ExprWithBlock> &get_else_block () { return else_block; }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  IfLetExprConseqElse *clone_expr_impl () const override
-  {
-    return new IfLetExprConseqElse (*this);
-  }
-
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  IfLetExprConseqElse *clone_expr_with_block_impl () const override
-  {
-    return new IfLetExprConseqElse (*this);
-  }
-
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  IfLetExprConseqElse *clone_if_let_expr_impl () const override
-  {
-    return new IfLetExprConseqElse (*this);
-  }
-};
-
 // Match arm expression
 struct MatchArm
 {
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h 
b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 7cc031870eba..0db8bd23404f 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -113,8 +113,6 @@ class WhileLoopExpr;
 class WhileLetLoopExpr;
 class IfExpr;
 class IfExprConseqElse;
-class IfLetExpr;
-class IfLetExprConseqElse;
 struct MatchArm;
 // class MatchCase;
 // class MatchCaseBlockExpr;
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h 
b/gcc/rust/hir/tree/rust-hir-visitor.h
index 840dc2e11226..d30901684b4c 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -81,8 +81,6 @@ public:
   virtual void visit (WhileLetLoopExpr &expr) = 0;
   virtual void visit (IfExpr &expr) = 0;
   virtual void visit (IfExprConseqElse &expr) = 0;
-  virtual void visit (IfLetExpr &expr) = 0;
-  virtual void visit (IfLetExprConseqElse &expr) = 0;
   virtual void visit (MatchExpr &expr) = 0;
   virtual void visit (AwaitExpr &expr) = 0;
   virtual void visit (AsyncBlockExpr &expr) = 0;
@@ -219,8 +217,6 @@ public:
   virtual void visit (WhileLetLoopExpr &) override {}
   virtual void visit (IfExpr &) override {}
   virtual void visit (IfExprConseqElse &) override {}
-  virtual void visit (IfLetExpr &) override {}
-  virtual void visit (IfLetExprConseqElse &) override {}
 
   virtual void visit (MatchExpr &) override {}
   virtual void visit (AwaitExpr &) override {}
@@ -448,8 +444,6 @@ public:
   virtual void visit (WhileLetLoopExpr &expr) = 0;
   virtual void visit (IfExpr &expr) = 0;
   virtual void visit (IfExprConseqElse &expr) = 0;
-  virtual void visit (IfLetExpr &expr) = 0;
-  virtual void visit (IfLetExprConseqElse &expr) = 0;
   virtual void visit (InlineAsm &expr) = 0;
   virtual void visit (MatchExpr &expr) = 0;
   virtual void visit (AwaitExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index d5ca95c1cc06..b00e147549e3 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -1571,41 +1571,6 @@ IfExprConseqElse::as_string () const
   return str;
 }
 
-std::string
-IfLetExpr::as_string () const
-{
-  std::string str ("IfLetExpr: ");
-
-  str += "\n Condition match arm patterns: ";
-  if (match_arm_patterns.empty ())
-    {
-      str += "none";
-    }
-  else
-    {
-      for (const auto &pattern : match_arm_patterns)
-       {
-         str += "\n  " + pattern->as_string ();
-       }
-    }
-
-  str += "\n Scrutinee expr: " + value->as_string ();
-
-  str += "\n If let block expr: " + if_block->as_string ();
-
-  return str;
-}
-
-std::string
-IfLetExprConseqElse::as_string () const
-{
-  std::string str = IfLetExpr::as_string ();
-
-  str += "\n Else expr: " + else_block->as_string ();
-
-  return str;
-}
-
 std::string
 RangeFromToInclExpr::as_string () const
 {
@@ -4149,18 +4114,6 @@ IfExprConseqElse::accept_vis (HIRFullVisitor &vis)
   vis.visit (*this);
 }
 
-void
-IfLetExpr::accept_vis (HIRFullVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-IfLetExprConseqElse::accept_vis (HIRFullVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 MatchExpr::accept_vis (HIRFullVisitor &vis)
 {
@@ -4911,18 +4864,6 @@ RangeFromToInclExpr::accept_vis (HIRExpressionVisitor 
&vis)
   vis.visit (*this);
 }
 
-void
-IfLetExprConseqElse::accept_vis (HIRExpressionVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-IfLetExpr::accept_vis (HIRExpressionVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 IfExprConseqElse::accept_vis (HIRExpressionVisitor &vis)
 {
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index e61249987a2c..784e12e57ab1 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -300,7 +300,6 @@ public:
     UnsafeBlock,
     BaseLoop,
     If,
-    IfLet,
     Match,
     Await,
     AsyncBlock,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 49f1bbb1a614..369e1fd270a7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -503,67 +503,6 @@ TypeCheckExpr::visit (HIR::IfExprConseqElse &expr)
     }
 }
 
-void
-TypeCheckExpr::visit (HIR::IfLetExpr &expr)
-{
-  // this needs to perform a least upper bound coercion on the blocks and then
-  // unify the scruintee and arms
-  TyTy::BaseType *scrutinee_tyty
-    = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
-
-  for (auto &pattern : expr.get_patterns ())
-    {
-      TyTy::BaseType *kase_arm_ty
-       = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
-
-      unify_site (expr.get_mappings ().get_hirid (),
-                 TyTy::TyWithLocation (scrutinee_tyty),
-                 TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
-                 expr.get_locus ());
-    }
-
-  TypeCheckExpr::Resolve (expr.get_if_block ().get ());
-
-  infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
-}
-
-void
-TypeCheckExpr::visit (HIR::IfLetExprConseqElse &expr)
-{
-  TyTy::BaseType *scrutinee_tyty
-    = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
-
-  for (auto &pattern : expr.get_patterns ())
-    {
-      TyTy::BaseType *kase_arm_ty
-       = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
-
-      unify_site (expr.get_mappings ().get_hirid (),
-                 TyTy::TyWithLocation (scrutinee_tyty),
-                 TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
-                 expr.get_locus ());
-    }
-
-  auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ().get ());
-  auto else_blk_resolved
-    = TypeCheckExpr::Resolve (expr.get_else_block ().get ());
-
-  if (if_blk_resolved->get_kind () == TyTy::NEVER)
-    infered = else_blk_resolved;
-  else if (else_blk_resolved->get_kind () == TyTy::NEVER)
-    infered = if_blk_resolved;
-  else
-    {
-      infered = unify_site (
-       expr.get_mappings ().get_hirid (),
-       TyTy::TyWithLocation (if_blk_resolved,
-                             expr.get_if_block ()->get_locus ()),
-       TyTy::TyWithLocation (else_blk_resolved,
-                             expr.get_else_block ()->get_locus ()),
-       expr.get_locus ());
-    }
-}
-
 void
 TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 2f4a2c52f6db..e8137306b7c5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -45,8 +45,6 @@ public:
   void visit (HIR::NegationExpr &expr) override;
   void visit (HIR::IfExpr &expr) override;
   void visit (HIR::IfExprConseqElse &expr) override;
-  void visit (HIR::IfLetExpr &expr) override;
-  void visit (HIR::IfLetExprConseqElse &) override;
   void visit (HIR::BlockExpr &expr) override;
   void visit (HIR::UnsafeBlockExpr &expr) override;
   void visit (HIR::ArrayIndexExpr &expr) override;
diff --git a/gcc/testsuite/rust/compile/if_let_expr.rs 
b/gcc/testsuite/rust/compile/if_let_expr.rs
index 7bab19a1ef03..b0879e5fadbb 100644
--- a/gcc/testsuite/rust/compile/if_let_expr.rs
+++ b/gcc/testsuite/rust/compile/if_let_expr.rs
@@ -7,8 +7,9 @@ pub enum Option<T> {
 }
 
 fn main() {
-    let x = Option::Some(3); // { dg-warning "unused name" }
-    let a = if let Option::Some(1) = x {
+    let x = Option::Some(3);
+
+    let a = if let Option::Some(1) = x {// { dg-warning "unused name" }
         1
     } else if x == Option::Some(2) {
         2
diff --git a/gcc/testsuite/rust/compile/if_let_expr_simple.rs 
b/gcc/testsuite/rust/compile/if_let_expr_simple.rs
new file mode 100644
index 000000000000..d7fb0afa7fd3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/if_let_expr_simple.rs
@@ -0,0 +1,12 @@
+enum MyOption {
+    Some(i32),
+    None,
+}
+
+pub fn toto(i : MyOption) -> i32 {
+    if let MyOption::Some(v) = i {
+        v
+    } else {
+        23i32
+    }
+}
diff --git a/gcc/testsuite/rust/compile/iflet.rs 
b/gcc/testsuite/rust/compile/iflet.rs
new file mode 100644
index 000000000000..6d46339610f5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/iflet.rs
@@ -0,0 +1,32 @@
+pub fn simple_iflet() -> i32 {
+    let mut res = 0;
+
+    enum E {
+        X(i32),
+    }
+    let v = E::X(4);
+    
+    if let E::X(n) = v {
+        res = 1;
+    }
+
+    res
+}
+
+pub fn simple_iflet_else() -> i32 {
+    let mut res = 0;
+
+    enum E {
+        X(i32),
+        Y,
+    }
+    let v = E::X(4);
+
+    if let E::Y = v {
+        res = 1;
+    } else {
+        res = 2;
+    }
+
+    res
+}
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index 47d651b22bdf..424ad6860945 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -223,4 +223,7 @@ issue-2203.rs
 issue-2499.rs
 issue-3032-1.rs
 issue-3032-2.rs
+# https://github.com/Rust-GCC/gccrs/issues/3189
+if_let_expr_simple.rs
+iflet.rs
 # please don't delete the trailing newline
diff --git a/gcc/testsuite/rust/execute/torture/iflet.rs 
b/gcc/testsuite/rust/execute/torture/iflet.rs
new file mode 100644
index 000000000000..da4e93ac3988
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/iflet.rs
@@ -0,0 +1,84 @@
+enum Res {
+    OK,
+    BAD,
+}
+
+enum LOption {
+    Some(i32),
+    None,
+}
+
+// Expect a Some(_)
+//
+// Check we can match a Some.
+fn test_can_destructure_Some(v: LOption) -> Res {
+    if let LOption::Some(v) = v {
+        return Res::OK;
+    }
+    return Res::BAD;
+}
+
+// Expect Some(100).
+//
+// Check we can destructure and the inner value is correct.
+fn test_inner_value_is_100(v: LOption) -> Res {
+    if let LOption::Some(v) = v {
+        return match v {
+            100 => Res::OK,
+            _   => Res::BAD,
+        }
+    }
+    return Res::BAD;
+}
+
+// Expect a None as actual parameter.
+//
+// Only when we FAIL to match a Some do we take the else and return OK.
+fn test_if_else(v: LOption) -> Res {
+    if let LOption::Some(v) = v {
+        return Res::BAD;
+    } else {
+        return Res::OK;
+    }
+}
+
+fn main() -> i32 {
+
+    // Passing a None, so the function should return BAD
+    match test_can_destructure_Some(LOption::None) {
+        Res::OK => return 1,
+        Res::BAD => (),
+    }
+
+    // Same, but with a Some, should return OK
+    match test_can_destructure_Some(LOption::Some(1)) {
+        Res::OK => (),
+        Res::BAD => return 1,
+    }
+
+    // Check the destructuring is correct by looking for Some(100)
+    match test_inner_value_is_100(LOption::Some(100)) {
+        Res::OK => (),
+        Res::BAD => return 1,
+    }
+
+    // ... passing Some(1) should return BAD
+    match test_inner_value_is_100(LOption::Some(1)) {
+        Res::OK => return 1,
+        Res::BAD => (),
+    }
+
+    // ... and so does passing None
+    match test_inner_value_is_100(LOption::None) {
+        Res::OK => return 1,
+        Res::BAD => (),
+    }
+
+    // Check if let... else ...
+    match test_if_else(LOption::None) {
+        Res::OK => (),
+        Res::BAD => return 1,
+    }
+
+    0
+}

Reply via email to