From 65712a1bdd233c5111ef137f29289c511b6b6386 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Nov 2024 17:36:34 +0000 Subject: [PATCH] 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#3231 Fixes Rust-GCC#2567 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (check_match_scrutinee): (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 --- gcc/rust/backend/rust-compile-expr.cc | 21 +++++++++---------- .../errors/rust-hir-pattern-analysis.cc | 3 +++ .../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(-) create mode 100644 gcc/testsuite/rust/compile/issue-2567-1.rs create mode 100644 gcc/testsuite/rust/compile/issue-2567-2.rs create mode 100644 gcc/testsuite/rust/compile/issue-2567-3.rs create mode 100644 gcc/testsuite/rust/compile/issue-3231.rs diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 615354fc9612..5047dfe9d8cf 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1014,17 +1014,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 (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. @@ -1065,6 +1055,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 ()) + { + 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 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 de68181049ca..7daa27195db6 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 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() {}