Add new tests and update existing for object-safe custom receivers
This commit is contained in:
parent
a0f23f8405
commit
82f1f9a5b4
6 changed files with 240 additions and 18 deletions
|
@ -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);
|
||||||
|
}
|
56
src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
Normal file
56
src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
Normal 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());
|
||||||
|
}
|
|
@ -12,38 +12,38 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn foo(self: Rc<Self>) -> usize;
|
fn foo(self: &Rc<Self>) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
fn foo(self: Rc<Self>) -> usize where Self: Sized;
|
fn foo(self: &Rc<Self>) -> usize where Self: Sized;
|
||||||
fn bar(self: Box<Self>) -> usize;
|
fn bar(self: Rc<Self>) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for usize {
|
impl Foo for usize {
|
||||||
fn foo(self: Rc<Self>) -> usize {
|
fn foo(self: &Rc<Self>) -> usize {
|
||||||
*self
|
**self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bar for usize {
|
impl Bar for usize {
|
||||||
fn foo(self: Rc<Self>) -> usize {
|
fn foo(self: &Rc<Self>) -> usize {
|
||||||
*self
|
**self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(self: Box<Self>) -> usize {
|
fn bar(self: Rc<Self>) -> usize {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_foo() {
|
fn make_foo() {
|
||||||
let x = Box::new(5usize) as Box<Foo>;
|
let x = Rc::new(5usize) as Rc<Foo>;
|
||||||
//~^ ERROR E0038
|
//~^ ERROR E0038
|
||||||
//~| ERROR E0038
|
//~| ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar() {
|
fn make_bar() {
|
||||||
let x = Box::new(5usize) as Box<Bar>;
|
let x = Rc::new(5usize) as Rc<Bar>;
|
||||||
x.bar();
|
x.bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
error[E0038]: the trait `Foo` cannot be made into an object
|
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>;
|
LL | let x = Rc::new(5usize) as Rc<Foo>;
|
||||||
| ^^^^^^^^ the trait `Foo` cannot be made into an object
|
| ^^^^^^^ 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
|
error[E0038]: the trait `Foo` cannot be made into an object
|
||||||
--> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
|
--> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
|
||||||
|
|
|
|
||||||
LL | let x = Box::new(5usize) as Box<Foo>;
|
LL | let x = Rc::new(5usize) as Rc<Foo>;
|
||||||
| ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
| ^^^^^^^^^^^^^^^ 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
|
||||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
|
= 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
54
src/test/ui/invalid_coerce_sized_impls.rs
Normal file
54
src/test/ui/invalid_coerce_sized_impls.rs
Normal 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() {}
|
33
src/test/ui/invalid_coerce_sized_impls.stderr
Normal file
33
src/test/ui/invalid_coerce_sized_impls.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue