Skip to content

Commit 5dc433a

Browse files
committed
Auto merge of #1039 - RalfJung:dyn-tests, r=RalfJung
More tests for dyn trait (in particular, unsized receivers) So far we only tested them indirectly through `dyn FnOnce`; this also adds some self-contained tests from the rustc test suite.
2 parents 0740a20 + 57dec5c commit 5dc433a

10 files changed

+159
-63
lines changed

tests/run-pass/box_box_trait.rs

Lines changed: 0 additions & 31 deletions
This file was deleted.

tests/run-pass/closures.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,21 @@ fn fn_once_closure_with_multiple_args() -> i64 {
4040
}
4141
}
4242

43-
fn boxed(f: Box<dyn FnOnce() -> i32>) -> i32 {
43+
fn boxed_fn_once(f: Box<dyn FnOnce() -> i32>) -> i32 {
4444
f()
4545
}
4646

47+
fn box_dyn() {
48+
let x: Box<dyn Fn(i32) -> i32> = Box::new(|x| x * 2);
49+
assert_eq!(x(21), 42);
50+
let mut i = 5;
51+
{
52+
let mut x: Box<dyn FnMut()> = Box::new(|| i *= 2);
53+
x(); x();
54+
}
55+
assert_eq!(i, 20);
56+
}
57+
4758
fn fn_item_as_closure_trait_object() {
4859
fn foo() {}
4960
let f: &dyn Fn() = &foo;
@@ -96,8 +107,9 @@ fn main() {
96107
assert_eq!(crazy_closure(), (84, 10, 10));
97108
assert_eq!(closure_arg_adjustment_problem(), 3);
98109
assert_eq!(fn_once_closure_with_multiple_args(), 6);
99-
assert_eq!(boxed(Box::new({let x = 13; move || x})), 13);
110+
assert_eq!(boxed_fn_once(Box::new({let x = 13; move || x})), 13);
100111

112+
box_dyn();
101113
fn_item_as_closure_trait_object();
102114
fn_item_with_args_as_closure_trait_object();
103115
fn_item_with_multiple_args_as_closure_trait_object();

tests/run-pass/dyn-traits.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#![feature(unsized_locals)]
2+
3+
fn ref_box_dyn() {
4+
struct Struct(i32);
5+
6+
trait Trait {
7+
fn method(&self);
8+
9+
fn box_method(self: Box<Self>);
10+
}
11+
12+
impl Trait for Struct {
13+
fn method(&self) {
14+
assert_eq!(self.0, 42);
15+
}
16+
17+
fn box_method(self: Box<Self>) {
18+
assert_eq!(self.0, 7);
19+
}
20+
}
21+
22+
struct Foo<T: ?Sized>(T);
23+
24+
let y: &dyn Trait = &Struct(42);
25+
y.method();
26+
27+
let x: Foo<Struct> = Foo(Struct(42));
28+
let y: &Foo<dyn Trait> = &x;
29+
y.0.method();
30+
31+
let y: Box<dyn Trait> = Box::new(Struct(42));
32+
y.method();
33+
34+
let y = &y;
35+
y.method();
36+
37+
let y: Box<dyn Trait> = Box::new(Struct(7));
38+
y.box_method();
39+
}
40+
41+
42+
fn box_box_trait() {
43+
struct DroppableStruct;
44+
45+
static mut DROPPED: bool = false;
46+
47+
impl Drop for DroppableStruct {
48+
fn drop(&mut self) {
49+
unsafe { DROPPED = true; }
50+
}
51+
}
52+
53+
trait MyTrait { fn dummy(&self) { } }
54+
impl MyTrait for Box<DroppableStruct> {}
55+
56+
struct Whatever { w: Box<dyn MyTrait+'static> }
57+
58+
impl Whatever {
59+
fn new(w: Box<dyn MyTrait+'static>) -> Whatever {
60+
Whatever { w: w }
61+
}
62+
}
63+
64+
{
65+
let f = Box::new(DroppableStruct);
66+
let a = Whatever::new(Box::new(f) as Box<dyn MyTrait>);
67+
a.w.dummy();
68+
}
69+
assert!(unsafe { DROPPED });
70+
}
71+
72+
fn unsized_dyn() {
73+
pub trait Foo {
74+
fn foo(self) -> String;
75+
}
76+
77+
struct A;
78+
79+
impl Foo for A {
80+
fn foo(self) -> String {
81+
format!("hello")
82+
}
83+
}
84+
85+
let x = *(Box::new(A) as Box<dyn Foo>);
86+
assert_eq!(x.foo(), format!("hello"));
87+
88+
// I'm not sure whether we want this to work
89+
let x = Box::new(A) as Box<dyn Foo>;
90+
assert_eq!(x.foo(), format!("hello"));
91+
}
92+
93+
fn unsized_dyn_autoderef() {
94+
pub trait Foo {
95+
fn foo(self) -> String;
96+
}
97+
98+
impl Foo for [char] {
99+
fn foo(self) -> String {
100+
self.iter().collect()
101+
}
102+
}
103+
104+
impl Foo for str {
105+
fn foo(self) -> String {
106+
self.to_owned()
107+
}
108+
}
109+
110+
impl Foo for dyn FnMut() -> String {
111+
fn foo(mut self) -> String {
112+
self()
113+
}
114+
}
115+
116+
let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>);
117+
assert_eq!(&x.foo() as &str, "hello");
118+
119+
let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>;
120+
assert_eq!(&x.foo() as &str, "hello");
121+
122+
let x = "hello".to_owned().into_boxed_str();
123+
assert_eq!(&x.foo() as &str, "hello");
124+
125+
let x = *("hello".to_owned().into_boxed_str());
126+
assert_eq!(&x.foo() as &str, "hello");
127+
128+
let x = "hello".to_owned().into_boxed_str();
129+
assert_eq!(&x.foo() as &str, "hello");
130+
131+
let x = *(Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>);
132+
assert_eq!(&x.foo() as &str, "hello");
133+
134+
let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
135+
assert_eq!(&x.foo() as &str, "hello");
136+
}
137+
138+
fn main() {
139+
ref_box_dyn();
140+
box_box_trait();
141+
142+
// "exotic" receivers
143+
unsized_dyn();
144+
unsized_dyn_autoderef();
145+
}

tests/run-pass/traits.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)