]> git.lizzy.rs Git - rust.git/commitdiff
Add new tests and update existing for object-safe custom receivers
authorMichael Hewson <michael@michaelhewson.ca>
Thu, 20 Sep 2018 07:28:57 +0000 (03:28 -0400)
committerMichael Hewson <michael@michaelhewson.ca>
Thu, 1 Nov 2018 22:16:22 +0000 (18:16 -0400)
src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs [new file with mode: 0644]
src/test/ui/arbitrary-self-types-not-object-safe.rs
src/test/ui/arbitrary-self-types-not-object-safe.stderr
src/test/ui/invalid_coerce_sized_impls.rs [new file with mode: 0644]
src/test/ui/invalid_coerce_sized_impls.stderr [new file with mode: 0644]

diff --git a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
new file mode 100644 (file)
index 0000000..3abe806
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types, unsize, coerce_unsized, coerce_sized)]
+#![feature(rustc_attrs)]
+
+use std::{
+    ops::{Deref, CoerceUnsized, CoerceSized},
+    marker::Unsize,
+    fmt::Debug,
+};
+
+struct Ptr<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized> Deref for Ptr<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.0
+    }
+}
+
+impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
+impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceSized<Ptr<T>> for Ptr<U> {}
+
+struct Wrapper<T: ?Sized>(T);
+
+impl<T: ?Sized> Deref for Wrapper<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
+impl<T: CoerceUnsized<U>, U: CoerceSized<T>> CoerceSized<Wrapper<T>> for Wrapper<U> {}
+
+
+trait Trait {
+    // This method can't be called on trait objects, since the receiver would be unsized,
+    // but should not cause an object safety error
+    // fn wrapper(self: Wrapper<Self>) -> i32;
+    fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
+    fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
+}
+
+impl Trait for i32 {
+    // fn wrapper(self: Wrapper<Self>) -> i32 {
+    //     *self
+    // }
+    fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
+        ***self
+    }
+}
+
+fn main() {
+    let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>;
+    assert_eq!(pw.ptr_wrapper(), 5);
+
+    let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>;
+    assert_eq!(wp.wrapper_ptr(), 6);
+
+    let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
+    assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
+}
diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
new file mode 100644 (file)
index 0000000..80a7ce9
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(arbitrary_self_types)]
+#![feature(pin)]
+#![feature(rustc_attrs)]
+
+use std::{
+    rc::Rc,
+    sync::Arc,
+    pin::Pin,
+};
+
+trait Trait {
+    fn by_rc(self: Rc<Self>) -> i64;
+    fn by_arc(self: Arc<Self>) -> i64;
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64;
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64;
+}
+
+impl Trait for i64 {
+    fn by_rc(self: Rc<Self>) -> i64 {
+        *self
+    }
+    fn by_arc(self: Arc<Self>) -> i64 {
+        *self
+    }
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64 {
+        *self
+    }
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
+        *self
+    }
+}
+
+fn main() {
+    let rc = Rc::new(1i64) as Rc<dyn Trait>;
+    assert_eq!(1, rc.by_rc());
+
+    let arc = Arc::new(2i64) as Arc<dyn Trait>;
+    assert_eq!(2, arc.by_arc());
+
+    let mut value = 3i64;
+    let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>;
+    assert_eq!(3, pin_mut.by_pin_mut());
+
+    let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
+    assert_eq!(4, pin_box.by_pin_box());
+}
index 48918b996ef5989aa9e9b67d10a805295fea5d26..4dc481174a45d4ac94a5690a256b5df4bd3f1435 100644 (file)
 use std::rc::Rc;
 
 trait Foo {
-    fn foo(self: Rc<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize;
 }
 
 trait Bar {
-    fn foo(self: Rc<Self>) -> usize where Self: Sized;
-    fn bar(self: Box<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize where Self: Sized;
+    fn bar(self: Rc<Self>) -> usize;
 }
 
 impl Foo for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 }
 
 impl Bar for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 
-    fn bar(self: Box<Self>) -> usize {
+    fn bar(self: Rc<Self>) -> usize {
         *self
     }
 }
 
 fn make_foo() {
-    let x = Box::new(5usize) as Box<Foo>;
+    let x = Rc::new(5usize) as Rc<Foo>;
     //~^ ERROR E0038
     //~| ERROR E0038
 }
 
 fn make_bar() {
-    let x = Box::new(5usize) as Box<Bar>;
+    let x = Rc::new(5usize) as Rc<Bar>;
     x.bar();
 }
 
index ec9e65fc4c62d3fb8717c1886e4a5d13bfdf4a76..715fc86517bee8eb0d0cf8069d5fbc753d4ec8ef 100644 (file)
@@ -1,19 +1,19 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:33
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:32
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |                                 ^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |                                ^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
+   = note: method `foo` has an uncoercible receiver type
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |             ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
-   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
+   = note: method `foo` has an uncoercible receiver type
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/invalid_coerce_sized_impls.rs b/src/test/ui/invalid_coerce_sized_impls.rs
new file mode 100644 (file)
index 0000000..27d65b8
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unsize, coerce_sized, coerce_unsized)]
+
+use std::{
+    ops::{CoerceSized, CoerceUnsized},
+    marker::{Unsize, PhantomData},
+};
+
+struct WrapperWithExtraField<T>(T, i32);
+
+impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+where
+    T: CoerceUnsized<U>,
+{}
+
+impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
+where
+    T: CoerceUnsized<U>,
+    U: CoerceSized<T>,
+{} //~^^^^ ERROR [E0378]
+
+
+struct MultiplePointers<T: ?Sized>{
+    ptr1: *const T,
+    ptr2: *const T,
+}
+
+// No CoerceUnsized impl
+
+impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct NothingToCoerce<T: ?Sized> {
+    data: PhantomData<T>,
+}
+
+// No CoerceUnsized impl
+
+impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
+//~^ ERROR [E0378]
+
+fn main() {}
diff --git a/src/test/ui/invalid_coerce_sized_impls.stderr b/src/test/ui/invalid_coerce_sized_impls.stderr
new file mode 100644 (file)
index 0000000..70fb464
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0378]: the trait `CoerceSized` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
+  --> $DIR/invalid_coerce_sized_impls.rs:25:1
+   |
+LL | / impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
+LL | | where
+LL | |     T: CoerceUnsized<U>,
+LL | |     U: CoerceSized<T>,
+LL | | {} //~^^^^ ERROR [E0378]
+   | |__^
+   |
+   = note: extra field `1` of type `i32` is not allowed
+
+error[E0378]: implementing the `CoerceSized` trait requires multiple coercions
+  --> $DIR/invalid_coerce_sized_impls.rs:39:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {} //~^^^ ERROR [E0378]
+   | |__^
+   |
+   = note: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced
+   = note: currently, 2 fields need coercions: ptr1 (*const U to *const T), ptr2 (*const U to *const T)
+
+error[E0378]: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced, none found
+  --> $DIR/invalid_coerce_sized_impls.rs:51:1
+   |
+LL | impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0378`.