[PATCH] Allow bool and char to be cast as any integer type

Mark Wielaard mark@klomp.org
Mon Aug 16 16:51:23 GMT 2021


bools and chars can be cast to any integer type, but not to floats or
each other. Adjust the BoolCastRule and CharCastRule to allow these
casts. Add a postive test "as_bool_char.rs" and negative test
"bad_as_bool_char.rs" to check the correct casts are accepted and the
illegal casts produce errors.

Resolves: https://github.com/Rust-GCC/gccrs/issues/629
---
 gcc/rust/typecheck/rust-tyty-cast.h           | 12 +++++++
 .../rust/compile/bad_as_bool_char.rs          | 18 ++++++++++
 .../rust/compile/torture/as_bool_char.rs      | 36 +++++++++++++++++++
 3 files changed, 66 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/bad_as_bool_char.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/as_bool_char.rs

diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
index de59b327e76..c457931b17f 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -779,6 +779,12 @@ public:
       }
   }
 
+  /* bools can be cast to any integer type (but not floats or chars).  */
+  void visit (IntType &type) override { resolved = type.clone (); }
+  void visit (UintType &type) override { resolved = type.clone (); }
+  void visit (USizeType &type) override { resolved = type.clone (); }
+  void visit (ISizeType &type) override { resolved = type.clone (); }
+
 private:
   BaseType *get_base () override { return base; }
 
@@ -1078,6 +1084,12 @@ public:
 
   void visit (CharType &type) override { resolved = type.clone (); }
 
+  /* chars can be cast to any integer type (but not floats or bools).  */
+  void visit (IntType &type) override { resolved = type.clone (); }
+  void visit (UintType &type) override { resolved = type.clone (); }
+  void visit (USizeType &type) override { resolved = type.clone (); }
+  void visit (ISizeType &type) override { resolved = type.clone (); }
+
 private:
   BaseType *get_base () override { return base; }
 
diff --git a/gcc/testsuite/rust/compile/bad_as_bool_char.rs b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
new file mode 100644
index 00000000000..91a28eebe00
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
@@ -0,0 +1,18 @@
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let fone = t as f32;   // { dg-error "invalid cast" }
+  let fzero = f as f64;  // { dg-error "invalid cast" }
+
+  let nb = 0u8 as bool;  // { dg-error "invalid cast" }
+  let nc = true as char; // { dg-error "invalid cast" }
+
+  let a = 'a';
+  let b = 'b';
+  let fa = a as f32;     // { dg-error "invalid cast" }
+  let bb = b as bool;    // { dg-error "invalid cast" }
+
+  let t32: u32 = 33;
+  let ab = t32 as char;  // { dg-error "invalid cast" }
+}
diff --git a/gcc/testsuite/rust/compile/torture/as_bool_char.rs b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
new file mode 100644
index 00000000000..d687499384a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
@@ -0,0 +1,36 @@
+extern "C" { fn abort (); }
+
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let one = t as u8;
+  let zero = f as u8;
+
+  if one != 1 || zero != 0 { unsafe { abort (); } }
+
+  let isizeone = true as isize;
+  let usizezero = false as usize;
+
+  if isizeone != 1 || usizezero != 0 { unsafe { abort (); } }
+
+  let i32zero = f as i32;
+  let u128one = t as u128;
+
+  if u128one != 1 || i32zero != 0 { unsafe { abort (); } }
+
+  let a = 'a';
+  let b = 'b';
+  let ua = a as u8;
+  let ib = b as i32;
+
+  if (ua + 1) as i32 != ib { unsafe { abort (); } }
+
+  let tt = ua;
+  let aa = tt as char;
+
+  let ttt = tt + 1;
+  let ab = ttt as char;
+
+  if aa != 'a' || ab != 'b' { unsafe { abort (); } }
+}
-- 
2.32.0



More information about the Gcc-rust mailing list