diff options
| author | Michael Hewson <michael@michaelhewson.ca> | 2018-09-20 03:28:57 -0400 |
|---|---|---|
| committer | Michael Hewson <michael@michaelhewson.ca> | 2018-11-01 18:16:22 -0400 |
| commit | 82f1f9a5b4ccd1eae1ac6f00d98f9fb61b94946d (patch) | |
| tree | 1badb24598b38ab454074c90e03200ed575e1241 | |
| parent | a0f23f8405c25b8547654b40ad5fa05fbe4c4b47 (diff) | |
| download | rust-82f1f9a5b4ccd1eae1ac6f00d98f9fb61b94946d.tar.gz rust-82f1f9a5b4ccd1eae1ac6f00d98f9fb61b94946d.zip | |
Add new tests and update existing for object-safe custom receivers
6 files changed, 240 insertions, 18 deletions
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 index 00000000000..3abe806c9a9 --- /dev/null +++ b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs @@ -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 index 00000000000..80a7ce96911 --- /dev/null +++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs @@ -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()); +} diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.rs b/src/test/ui/arbitrary-self-types-not-object-safe.rs index 48918b996ef..4dc481174a4 100644 --- a/src/test/ui/arbitrary-self-types-not-object-safe.rs +++ b/src/test/ui/arbitrary-self-types-not-object-safe.rs @@ -12,38 +12,38 @@ 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(); } diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/arbitrary-self-types-not-object-safe.stderr index ec9e65fc4c6..715fc86517b 100644 --- a/src/test/ui/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/arbitrary-self-types-not-object-safe.stderr @@ -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 index 00000000000..27d65b880fa --- /dev/null +++ b/src/test/ui/invalid_coerce_sized_impls.rs @@ -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 index 00000000000..70fb464d426 --- /dev/null +++ b/src/test/ui/invalid_coerce_sized_impls.stderr @@ -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`. |
