aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2024-11-21 17:36:34 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-21 12:33:02 +0100
commite4a92d706b30fb2e5c39161dc1ff9f4eabbec983 (patch)
tree63a39eb2b7919eeb6b933985ed8e338631e5fc6a /gcc
parent6e90ff47c658f5a5e97b4b3ae1501efb6e076303 (diff)
downloadgcc-e4a92d706b30fb2e5c39161dc1ff9f4eabbec983.zip
gcc-e4a92d706b30fb2e5c39161dc1ff9f4eabbec983.tar.gz
gcc-e4a92d706b30fb2e5c39161dc1ff9f4eabbec983.tar.bz2
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.philip@googlemail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc21
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc12
-rw-r--r--gcc/testsuite/rust/compile/exhaustiveness1.rs4
-rw-r--r--gcc/testsuite/rust/compile/issue-2567-1.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-2567-2.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-2567-3.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3231.rs8
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 7ea2a67..e0fb1da 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 617d754..db1e727 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 03922bb..5a96c35 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 fe95ea3..356636b 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 0000000..f5af249
--- /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 0000000..719511d
--- /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 0000000..09efaf0
--- /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 0000000..59726cb
--- /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() {}