https://gcc.gnu.org/g:e4a92d706b30fb2e5c39161dc1ff9f4eabbec983

commit r15-8542-ge4a92d706b30fb2e5c39161dc1ff9f4eabbec983
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Thu Nov 21 17:36:34 2024 +0000

    gccrs: empty match expressions should resolve to !
    
    This is a special case in Rust and the ! type can unify with pretty much
    anything its almost a inference variable and a unit-type for special cases.
    
    Fixes Rust-GCC/gccrs#3231
    Fixes Rust-GCC/gccrs#2567
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-expr.cc (check_match_scrutinee): check for 
empty match
            (CompileExpr::visit): fix assertion
            * checks/errors/rust-hir-pattern-analysis.cc 
(check_match_usefulness): check for empty
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
resolve to !
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/exhaustiveness1.rs: remove bad check
            * rust/compile/issue-2567-1.rs: New test.
            * rust/compile/issue-2567-2.rs: New test.
            * rust/compile/issue-2567-3.rs: New test.
            * rust/compile/issue-3231.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/backend/rust-compile-expr.cc               | 21 ++++++++++-----------
 gcc/rust/checks/errors/rust-hir-pattern-analysis.cc |  3 +++
 gcc/rust/typecheck/rust-hir-type-check-expr.cc      | 12 ++++++++++++
 gcc/testsuite/rust/compile/exhaustiveness1.rs       |  4 +---
 gcc/testsuite/rust/compile/issue-2567-1.rs          |  8 ++++++++
 gcc/testsuite/rust/compile/issue-2567-2.rs          |  8 ++++++++
 gcc/testsuite/rust/compile/issue-2567-3.rs          |  8 ++++++++
 gcc/testsuite/rust/compile/issue-3231.rs            |  8 ++++++++
 8 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 7ea2a6755221..e0fb1da3feb3 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1013,17 +1013,7 @@ check_match_scrutinee (HIR::MatchExpr &expr, Context 
*ctx)
               || scrutinee_kind == TyTy::TypeKind::TUPLE
               || scrutinee_kind == TyTy::TypeKind::REF);
 
-  if (scrutinee_kind == TyTy::TypeKind::ADT)
-    {
-      // this will need to change but for now the first pass implementation,
-      // lets assert this is the case
-      TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (scrutinee_expr_tyty);
-      if (adt->is_enum ())
-       rust_assert (adt->number_of_variants () > 0);
-      else
-       rust_assert (adt->number_of_variants () == 1);
-    }
-  else if (scrutinee_kind == TyTy::TypeKind::FLOAT)
+  if (scrutinee_kind == TyTy::TypeKind::FLOAT)
     {
       // FIXME: CASE_LABEL_EXPR does not support floating point types.
       // Find another way to compile these.
@@ -1064,6 +1054,15 @@ CompileExpr::visit (HIR::MatchExpr &expr)
       return;
     }
 
+  // if the result of this expression is meant to be never type then we can
+  // optimise this away but there is the case where match arms resolve to !
+  // because of return statements we need to special case this
+  if (!expr.has_match_arms () && expr_tyty->is<TyTy::NeverType> ())
+    {
+      translated = unit_expression (expr.get_locus ());
+      return;
+    }
+
   fncontext fnctx = ctx->peek_fn ();
   Bvariable *tmp = NULL;
   tree enclosing_scope = ctx->peek_enclosing_scope ();
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 617d754c1819..db1e72725565 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -1530,6 +1530,9 @@ void
 check_match_usefulness (Resolver::TypeCheckContext *ctx,
                        TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr)
 {
+  if (!expr.has_match_arms ())
+    return;
+
   // Lower the arms to a more convenient representation.
   std::vector<MatrixRow> rows;
   for (auto &arm : expr.get_match_cases ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 03922bb554ce..5a96c359d7c5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1456,6 +1456,18 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
   TyTy::BaseType *scrutinee_tyty
     = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ());
 
+  // https://github.com/Rust-GCC/gccrs/issues/3231#issuecomment-2462660048
+  // 
https://github.com/rust-lang/rust/blob/3d1dba830a564d1118361345d7ada47a05241f45/compiler/rustc_hir_typeck/src/_match.rs#L32-L36
+  if (!expr.has_match_arms ())
+    {
+      // this is a special case where rustc returns !
+      TyTy::BaseType *lookup = nullptr;
+      bool ok = context->lookup_builtin ("!", &lookup);
+      rust_assert (ok);
+      infered = lookup->clone ();
+      return;
+    }
+
   bool saw_error = false;
   std::vector<TyTy::BaseType *> kase_block_tys;
   for (auto &kase : expr.get_match_cases ())
diff --git a/gcc/testsuite/rust/compile/exhaustiveness1.rs 
b/gcc/testsuite/rust/compile/exhaustiveness1.rs
index fe95ea3c9d9c..356636b4e1fb 100644
--- a/gcc/testsuite/rust/compile/exhaustiveness1.rs
+++ b/gcc/testsuite/rust/compile/exhaustiveness1.rs
@@ -15,9 +15,7 @@ fn s2(s: S) {
 }
 
 fn s3(s: S) {
-    match s {
-        // { dg-error "non-exhaustive patterns: '_' not covered" "" { target 
*-*-* } .-1 }
-    }
+    match s {}
 }
 
 enum E {
diff --git a/gcc/testsuite/rust/compile/issue-2567-1.rs 
b/gcc/testsuite/rust/compile/issue-2567-1.rs
new file mode 100644
index 000000000000..f5af24936193
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2567-1.rs
@@ -0,0 +1,8 @@
+// { dg-options "-w" }
+enum Empty {}
+
+fn foo(x: Empty) {
+    let x: Empty = match x {
+        // empty
+    };
+}
diff --git a/gcc/testsuite/rust/compile/issue-2567-2.rs 
b/gcc/testsuite/rust/compile/issue-2567-2.rs
new file mode 100644
index 000000000000..719511d49d3e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2567-2.rs
@@ -0,0 +1,8 @@
+// { dg-options "-w" }
+enum Empty {}
+
+fn foo(x: Empty) {
+    let x: i32 = match x {
+        // empty
+    };
+}
diff --git a/gcc/testsuite/rust/compile/issue-2567-3.rs 
b/gcc/testsuite/rust/compile/issue-2567-3.rs
new file mode 100644
index 000000000000..09efaf0af8be
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2567-3.rs
@@ -0,0 +1,8 @@
+// { dg-options "-w" }
+enum Empty {}
+
+fn foo(x: Empty) {
+    match x {
+        // empty
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3231.rs 
b/gcc/testsuite/rust/compile/issue-3231.rs
new file mode 100644
index 000000000000..59726cb7b753
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3231.rs
@@ -0,0 +1,8 @@
+// { dg-options "-w" }
+pub enum X {}
+
+pub fn foo(x: X) {
+    let _a: i32 = match x {};
+}
+
+pub fn main() {}

Reply via email to