1
Fork 0

Add new tests and update existing for object-safe custom receivers

This commit is contained in:
Michael Hewson 2018-09-20 03:28:57 -04:00
parent a0f23f8405
commit 82f1f9a5b4
6 changed files with 240 additions and 18 deletions

View file

@ -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);
}

View file

@ -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());
}

View file

@ -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();
}

View 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

View file

@ -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() {}

View file

@ -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`.