From 82f1f9a5b4ccd1eae1ac6f00d98f9fb61b94946d Mon Sep 17 00:00:00 2001 From: Michael Hewson Date: Thu, 20 Sep 2018 03:28:57 -0400 Subject: [PATCH] Add new tests and update existing for object-safe custom receivers --- ...itrary_self_types_pointers_and_wrappers.rs | 79 +++++++++++++++++++ .../arbitrary_self_types_stdlib_pointers.rs | 56 +++++++++++++ .../arbitrary-self-types-not-object-safe.rs | 20 ++--- ...rbitrary-self-types-not-object-safe.stderr | 16 ++-- src/test/ui/invalid_coerce_sized_impls.rs | 54 +++++++++++++ src/test/ui/invalid_coerce_sized_impls.stderr | 33 ++++++++ 6 files changed, 240 insertions(+), 18 deletions(-) create mode 100644 src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs create mode 100644 src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs create mode 100644 src/test/ui/invalid_coerce_sized_impls.rs create mode 100644 src/test/ui/invalid_coerce_sized_impls.stderr 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 or the MIT license +// , 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(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} +impl + ?Sized, U: ?Sized> CoerceSized> for Ptr {} + +struct Wrapper(T); + +impl Deref for Wrapper { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl, U> CoerceUnsized> for Wrapper {} +impl, U: CoerceSized> CoerceSized> for Wrapper {} + + +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) -> i32; + fn ptr_wrapper(self: Ptr>) -> i32; + fn wrapper_ptr(self: Wrapper>) -> i32; + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; +} + +impl Trait for i32 { + // fn wrapper(self: Wrapper) -> i32 { + // *self + // } + fn ptr_wrapper(self: Ptr>) -> i32 { + **self + } + fn wrapper_ptr(self: Wrapper>) -> i32 { + **self + } + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32 { + ***self + } +} + +fn main() { + let pw = Ptr(Box::new(Wrapper(5))) as Ptr>; + assert_eq!(pw.ptr_wrapper(), 5); + + let wp = Wrapper(Ptr(Box::new(6))) as Wrapper>; + assert_eq!(wp.wrapper_ptr(), 6); + + let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper>>; + 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 or the MIT license +// , 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) -> i64; + fn by_arc(self: Arc) -> i64; + fn by_pin_mut(self: Pin<&mut Self>) -> i64; + fn by_pin_box(self: Pin>) -> i64; +} + +impl Trait for i64 { + fn by_rc(self: Rc) -> i64 { + *self + } + fn by_arc(self: Arc) -> i64 { + *self + } + fn by_pin_mut(self: Pin<&mut Self>) -> i64 { + *self + } + fn by_pin_box(self: Pin>) -> i64 { + *self + } +} + +fn main() { + let rc = Rc::new(1i64) as Rc; + assert_eq!(1, rc.by_rc()); + + let arc = Arc::new(2i64) as Arc; + 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::>>::into(Box::new(4i64)) as Pin>; + 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) -> usize; + fn foo(self: &Rc) -> usize; } trait Bar { - fn foo(self: Rc) -> usize where Self: Sized; - fn bar(self: Box) -> usize; + fn foo(self: &Rc) -> usize where Self: Sized; + fn bar(self: Rc) -> usize; } impl Foo for usize { - fn foo(self: Rc) -> usize { - *self + fn foo(self: &Rc) -> usize { + **self } } impl Bar for usize { - fn foo(self: Rc) -> usize { - *self + fn foo(self: &Rc) -> usize { + **self } - fn bar(self: Box) -> usize { + fn bar(self: Rc) -> usize { *self } } fn make_foo() { - let x = Box::new(5usize) as Box; + let x = Rc::new(5usize) as Rc; //~^ ERROR E0038 //~| ERROR E0038 } fn make_bar() { - let x = Box::new(5usize) as Box; + let x = Rc::new(5usize) as Rc; 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; - | ^^^^^^^^ the trait `Foo` cannot be made into an object +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^ 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; - | ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ 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>` for `std::boxed::Box` + = note: method `foo` has an uncoercible receiver type + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` 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 or the MIT license +// , 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, i32); + +impl CoerceUnsized> for WrapperWithExtraField +where + T: CoerceUnsized, +{} + +impl CoerceSized> for WrapperWithExtraField +where + T: CoerceUnsized, + U: CoerceSized, +{} //~^^^^ ERROR [E0378] + + +struct MultiplePointers{ + ptr1: *const T, + ptr2: *const T, +} + +// No CoerceUnsized impl + +impl CoerceSized> for MultiplePointers +where + T: Unsize, +{} //~^^^ ERROR [E0378] + + +struct NothingToCoerce { + data: PhantomData, +} + +// No CoerceUnsized impl + +impl CoerceSized> for NothingToCoerce {} +//~^ 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 CoerceSized> for WrapperWithExtraField +LL | | where +LL | | T: CoerceUnsized, +LL | | U: CoerceSized, +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 CoerceSized> for MultiplePointers +LL | | where +LL | | T: Unsize, +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 CoerceSized> for NothingToCoerce {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0378`.