aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2024-03-06 16:19:46 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2024-04-03 19:39:19 +0000
commitfbf35de5dcf89706452513b2ce2926fe95b38daa (patch)
tree43bac5107d8d37e3514fabea932b4483c68a0cd0 /gcc
parentd9f7604e8e8fadb4e10542d4c5f0004b19de2d96 (diff)
downloadgcc-fbf35de5dcf89706452513b2ce2926fe95b38daa.zip
gcc-fbf35de5dcf89706452513b2ce2926fe95b38daa.tar.gz
gcc-fbf35de5dcf89706452513b2ce2926fe95b38daa.tar.bz2
unify: Always coerce `!` to the target type.
Never can... never... exist, so it should always be coerced to the type it is being matched against. This is useful for breaking off of a loop from inside a match, or an if condition, for example. gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::go): Always unify to `ltype` if we are matching against a `Never` in `rtype`. (UnifyRules::expect_never): Always unify to the expected type. gcc/testsuite/ChangeLog: * rust/compile/match-never-ltype.rs: New test. * rust/compile/match-never-rtype.rs: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-unify.cc36
-rw-r--r--gcc/testsuite/rust/compile/match-never-ltype.rs17
-rw-r--r--gcc/testsuite/rust/compile/match-never-rtype.rs17
3 files changed, 45 insertions, 25 deletions
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 8b43380..7d1042d 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Resolver {
@@ -237,6 +238,15 @@ UnifyRules::go ()
}
}
+ // The never type should always get coerced to the type it's being matched
+ // against, so in that case, ltype. This avoids doing the same check in all
+ // the `expect_*` functions.
+ // However, this does not work if we have an annoying ltype - like INFER.
+ // TODO: Is ltype == Infer the only special case here? What about projections?
+ // references?
+ if (rtype->get_kind () == TyTy::NEVER && ltype->get_kind () != TyTy::INFER)
+ return ltype->clone ();
+
switch (ltype->get_kind ())
{
case TyTy::INFER:
@@ -1536,32 +1546,8 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::NEVER:
+ default:
return rtype->clone ();
-
- case TyTy::PLACEHOLDER:
- case TyTy::PROJECTION:
- case TyTy::DYNAMIC:
- case TyTy::CLOSURE:
- case TyTy::SLICE:
- case TyTy::PARAM:
- case TyTy::POINTER:
- case TyTy::STR:
- case TyTy::ADT:
- case TyTy::REF:
- case TyTy::ARRAY:
- case TyTy::FNDEF:
- case TyTy::FNPTR:
- case TyTy::TUPLE:
- case TyTy::BOOL:
- case TyTy::CHAR:
- case TyTy::INT:
- case TyTy::UINT:
- case TyTy::FLOAT:
- case TyTy::USIZE:
- case TyTy::ISIZE:
- case TyTy::ERROR:
- return new TyTy::ErrorType (0);
}
return new TyTy::ErrorType (0);
}
diff --git a/gcc/testsuite/rust/compile/match-never-ltype.rs b/gcc/testsuite/rust/compile/match-never-ltype.rs
new file mode 100644
index 0000000..6516ab3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-never-ltype.rs
@@ -0,0 +1,17 @@
+fn foo() {}
+
+enum Foo {
+ A,
+ B,
+}
+
+fn main() {
+ let a = Foo::A;
+
+ loop {
+ match a {
+ Foo::A => break,
+ Foo::B => foo(),
+ }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/match-never-rtype.rs b/gcc/testsuite/rust/compile/match-never-rtype.rs
new file mode 100644
index 0000000..6e4e763
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-never-rtype.rs
@@ -0,0 +1,17 @@
+fn foo() {}
+
+enum Foo {
+ A,
+ B,
+}
+
+fn main() {
+ let a = Foo::A;
+
+ loop {
+ match a {
+ Foo::B => foo(),
+ Foo::A => break,
+ }
+ }
+}