gccrs: Add general TypeBounds checks
authorPhilip Herron <herron.philip@googlemail.com>
Sat, 4 Feb 2023 22:53:48 +0000 (22:53 +0000)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 6 Apr 2023 08:47:21 +0000 (10:47 +0200)
Existing tests are updated to use libcore copy and clone implementation.

Addresses #1725

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/ChangeLog:

* typecheck/rust-unify.cc (UnifyRules::go): ensure the bounds are checked

gcc/testsuite/ChangeLog:

* rust/compile/torture/intrinsics-4.rs: implement Copy trait
* rust/compile/torture/intrinsics-5.rs: likewise
* rust/execute/torture/atomic_load.rs: likewise
* rust/execute/torture/atomic_store.rs: likewise
* rust/bounds1.rs: New test.

gcc/rust/typecheck/rust-unify.cc
gcc/testsuite/rust/bounds1.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/torture/intrinsics-4.rs
gcc/testsuite/rust/compile/torture/intrinsics-5.rs
gcc/testsuite/rust/execute/torture/atomic_load.rs
gcc/testsuite/rust/execute/torture/atomic_store.rs

index 072f761..415ffcd 100644 (file)
@@ -124,6 +124,17 @@ UnifyRules::go ()
   rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
              rtype->debug_str ().c_str ());
 
+  // check bounds
+  if (ltype->num_specified_bounds () > 0)
+    {
+      if (!ltype->bounds_compatible (*rtype, locus, true))
+       {
+         // already emitted an error
+         emit_error = false;
+         return new TyTy::ErrorType (0);
+       }
+    }
+
   switch (ltype->get_kind ())
     {
     case TyTy::INFER:
diff --git a/gcc/testsuite/rust/bounds1.rs b/gcc/testsuite/rust/bounds1.rs
new file mode 100644 (file)
index 0000000..6658360
--- /dev/null
@@ -0,0 +1,19 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 }
+    a + a
+}
+
+pub fn main() {
+    foo(123f32);
+}
index 243d446..4e09f10 100644 (file)
@@ -1,10 +1,67 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
-    // pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
 }
 
 fn main() {
@@ -15,6 +72,6 @@ fn main() {
         atomic_store_seqcst(&mut dst, new_value);
         atomic_store_release(&mut dst, new_value);
         atomic_store_relaxed(&mut dst, new_value);
-        // atomic_store_unordered(&mut dst, new_value);
+        atomic_store_unordered(&mut dst, new_value);
     }
 }
index 7fd84dc..ffad0bd 100644 (file)
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, value: T);
@@ -24,6 +81,13 @@ impl VeryLargeType {
     }
 }
 
+impl Clone for VeryLargeType {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+impl Copy for VeryLargeType {}
+
 fn main() {
     let mut dst = VeryLargeType::new(0);
     let mut b = false;
index 28ed8ae..6e7383a 100644 (file)
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
index 9f248b4..46960a7 100644 (file)
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+    fn clone(&self) -> Self;
+
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone()
+    }
+}
+
+mod impls {
+    use super::Clone;
+
+    macro_rules! impl_clone {
+        ($($t:ty)*) => {
+            $(
+                impl Clone for $t {
+                    fn clone(&self) -> Self {
+                        *self
+                    }
+                }
+            )*
+        }
+    }
+
+    impl_clone! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+    // Empty.
+}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
 
 extern "rust-intrinsic" {
     pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);