Skip to content

Commit 82f1f9a

Browse files
committed
Add new tests and update existing for object-safe custom receivers
1 parent a0f23f8 commit 82f1f9a

6 files changed

+240
-18
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#![feature(arbitrary_self_types, unsize, coerce_unsized, coerce_sized)]
11+
#![feature(rustc_attrs)]
12+
13+
use std::{
14+
ops::{Deref, CoerceUnsized, CoerceSized},
15+
marker::Unsize,
16+
fmt::Debug,
17+
};
18+
19+
struct Ptr<T: ?Sized>(Box<T>);
20+
21+
impl<T: ?Sized> Deref for Ptr<T> {
22+
type Target = T;
23+
24+
fn deref(&self) -> &T {
25+
&*self.0
26+
}
27+
}
28+
29+
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
30+
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceSized<Ptr<T>> for Ptr<U> {}
31+
32+
struct Wrapper<T: ?Sized>(T);
33+
34+
impl<T: ?Sized> Deref for Wrapper<T> {
35+
type Target = T;
36+
37+
fn deref(&self) -> &T {
38+
&self.0
39+
}
40+
}
41+
42+
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
43+
impl<T: CoerceUnsized<U>, U: CoerceSized<T>> CoerceSized<Wrapper<T>> for Wrapper<U> {}
44+
45+
46+
trait Trait {
47+
// This method can't be called on trait objects, since the receiver would be unsized,
48+
// but should not cause an object safety error
49+
// fn wrapper(self: Wrapper<Self>) -> i32;
50+
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
51+
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
52+
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
53+
}
54+
55+
impl Trait for i32 {
56+
// fn wrapper(self: Wrapper<Self>) -> i32 {
57+
// *self
58+
// }
59+
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
60+
**self
61+
}
62+
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
63+
**self
64+
}
65+
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
66+
***self
67+
}
68+
}
69+
70+
fn main() {
71+
let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>;
72+
assert_eq!(pw.ptr_wrapper(), 5);
73+
74+
let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>;
75+
assert_eq!(wp.wrapper_ptr(), 6);
76+
77+
let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
78+
assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
79+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(arbitrary_self_types)]
12+
#![feature(pin)]
13+
#![feature(rustc_attrs)]
14+
15+
use std::{
16+
rc::Rc,
17+
sync::Arc,
18+
pin::Pin,
19+
};
20+
21+
trait Trait {
22+
fn by_rc(self: Rc<Self>) -> i64;
23+
fn by_arc(self: Arc<Self>) -> i64;
24+
fn by_pin_mut(self: Pin<&mut Self>) -> i64;
25+
fn by_pin_box(self: Pin<Box<Self>>) -> i64;
26+
}
27+
28+
impl Trait for i64 {
29+
fn by_rc(self: Rc<Self>) -> i64 {
30+
*self
31+
}
32+
fn by_arc(self: Arc<Self>) -> i64 {
33+
*self
34+
}
35+
fn by_pin_mut(self: Pin<&mut Self>) -> i64 {
36+
*self
37+
}
38+
fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
39+
*self
40+
}
41+
}
42+
43+
fn main() {
44+
let rc = Rc::new(1i64) as Rc<dyn Trait>;
45+
assert_eq!(1, rc.by_rc());
46+
47+
let arc = Arc::new(2i64) as Arc<dyn Trait>;
48+
assert_eq!(2, arc.by_arc());
49+
50+
let mut value = 3i64;
51+
let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>;
52+
assert_eq!(3, pin_mut.by_pin_mut());
53+
54+
let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
55+
assert_eq!(4, pin_box.by_pin_box());
56+
}

src/test/ui/arbitrary-self-types-not-object-safe.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,38 @@
1212
use std::rc::Rc;
1313

1414
trait Foo {
15-
fn foo(self: Rc<Self>) -> usize;
15+
fn foo(self: &Rc<Self>) -> usize;
1616
}
1717

1818
trait Bar {
19-
fn foo(self: Rc<Self>) -> usize where Self: Sized;
20-
fn bar(self: Box<Self>) -> usize;
19+
fn foo(self: &Rc<Self>) -> usize where Self: Sized;
20+
fn bar(self: Rc<Self>) -> usize;
2121
}
2222

2323
impl Foo for usize {
24-
fn foo(self: Rc<Self>) -> usize {
25-
*self
24+
fn foo(self: &Rc<Self>) -> usize {
25+
**self
2626
}
2727
}
2828

2929
impl Bar for usize {
30-
fn foo(self: Rc<Self>) -> usize {
31-
*self
30+
fn foo(self: &Rc<Self>) -> usize {
31+
**self
3232
}
3333

34-
fn bar(self: Box<Self>) -> usize {
34+
fn bar(self: Rc<Self>) -> usize {
3535
*self
3636
}
3737
}
3838

3939
fn make_foo() {
40-
let x = Box::new(5usize) as Box<Foo>;
40+
let x = Rc::new(5usize) as Rc<Foo>;
4141
//~^ ERROR E0038
4242
//~| ERROR E0038
4343
}
4444

4545
fn make_bar() {
46-
let x = Box::new(5usize) as Box<Bar>;
46+
let x = Rc::new(5usize) as Rc<Bar>;
4747
x.bar();
4848
}
4949

src/test/ui/arbitrary-self-types-not-object-safe.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
error[E0038]: the trait `Foo` cannot be made into an object
2-
--> $DIR/arbitrary-self-types-not-object-safe.rs:40:33
2+
--> $DIR/arbitrary-self-types-not-object-safe.rs:40:32
33
|
4-
LL | let x = Box::new(5usize) as Box<Foo>;
5-
| ^^^^^^^^ the trait `Foo` cannot be made into an object
4+
LL | let x = Rc::new(5usize) as Rc<Foo>;
5+
| ^^^^^^^ the trait `Foo` cannot be made into an object
66
|
7-
= note: method `foo` has a non-standard `self` type
7+
= note: method `foo` has an uncoercible receiver type
88

99
error[E0038]: the trait `Foo` cannot be made into an object
1010
--> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
1111
|
12-
LL | let x = Box::new(5usize) as Box<Foo>;
13-
| ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
12+
LL | let x = Rc::new(5usize) as Rc<Foo>;
13+
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
1414
|
15-
= note: method `foo` has a non-standard `self` type
16-
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
15+
= note: method `foo` has an uncoercible receiver type
16+
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
1717

1818
error: aborting due to 2 previous errors
1919

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(unsize, coerce_sized, coerce_unsized)]
12+
13+
use std::{
14+
ops::{CoerceSized, CoerceUnsized},
15+
marker::{Unsize, PhantomData},
16+
};
17+
18+
struct WrapperWithExtraField<T>(T, i32);
19+
20+
impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
21+
where
22+
T: CoerceUnsized<U>,
23+
{}
24+
25+
impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
26+
where
27+
T: CoerceUnsized<U>,
28+
U: CoerceSized<T>,
29+
{} //~^^^^ ERROR [E0378]
30+
31+
32+
struct MultiplePointers<T: ?Sized>{
33+
ptr1: *const T,
34+
ptr2: *const T,
35+
}
36+
37+
// No CoerceUnsized impl
38+
39+
impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
40+
where
41+
T: Unsize<U>,
42+
{} //~^^^ ERROR [E0378]
43+
44+
45+
struct NothingToCoerce<T: ?Sized> {
46+
data: PhantomData<T>,
47+
}
48+
49+
// No CoerceUnsized impl
50+
51+
impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
52+
//~^ ERROR [E0378]
53+
54+
fn main() {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0378]: the trait `CoerceSized` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
2+
--> $DIR/invalid_coerce_sized_impls.rs:25:1
3+
|
4+
LL | / impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
5+
LL | | where
6+
LL | | T: CoerceUnsized<U>,
7+
LL | | U: CoerceSized<T>,
8+
LL | | {} //~^^^^ ERROR [E0378]
9+
| |__^
10+
|
11+
= note: extra field `1` of type `i32` is not allowed
12+
13+
error[E0378]: implementing the `CoerceSized` trait requires multiple coercions
14+
--> $DIR/invalid_coerce_sized_impls.rs:39:1
15+
|
16+
LL | / impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
17+
LL | | where
18+
LL | | T: Unsize<U>,
19+
LL | | {} //~^^^ ERROR [E0378]
20+
| |__^
21+
|
22+
= note: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced
23+
= note: currently, 2 fields need coercions: ptr1 (*const U to *const T), ptr2 (*const U to *const T)
24+
25+
error[E0378]: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced, none found
26+
--> $DIR/invalid_coerce_sized_impls.rs:51:1
27+
|
28+
LL | impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: aborting due to 3 previous errors
32+
33+
For more information about this error, try `rustc --explain E0378`.

0 commit comments

Comments
 (0)