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.
This commit is contained in:
bors
2019-11-07 08:18:09 +00:00
10 changed files with 159 additions and 63 deletions
-31
View File
@@ -1,31 +0,0 @@
#![feature(box_syntax)]
struct DroppableStruct;
static mut DROPPED: bool = false;
impl Drop for DroppableStruct {
fn drop(&mut self) {
unsafe { DROPPED = true; }
}
}
trait MyTrait { fn dummy(&self) { } }
impl MyTrait for Box<DroppableStruct> {}
#[allow(dead_code)]
struct Whatever { w: Box<dyn MyTrait+'static> }
impl Whatever {
fn new(w: Box<dyn MyTrait+'static>) -> Whatever {
Whatever { w: w }
}
}
fn main() {
{
let f: Box<_> = box DroppableStruct;
let _a = Whatever::new(box f as Box<dyn MyTrait>);
}
assert!(unsafe { DROPPED });
}
+14 -2
View File
@@ -40,10 +40,21 @@ fn once<F: FnOnce(i64, i64) -> i64>(f: F) -> i64 { f(2, 3) }
}
}
fn boxed(f: Box<dyn FnOnce() -> i32>) -> i32 {
fn boxed_fn_once(f: Box<dyn FnOnce() -> i32>) -> i32 {
f()
}
fn box_dyn() {
let x: Box<dyn Fn(i32) -> i32> = Box::new(|x| x * 2);
assert_eq!(x(21), 42);
let mut i = 5;
{
let mut x: Box<dyn FnMut()> = Box::new(|| i *= 2);
x(); x();
}
assert_eq!(i, 20);
}
fn fn_item_as_closure_trait_object() {
fn foo() {}
let f: &dyn Fn() = &foo;
@@ -96,8 +107,9 @@ fn main() {
assert_eq!(crazy_closure(), (84, 10, 10));
assert_eq!(closure_arg_adjustment_problem(), 3);
assert_eq!(fn_once_closure_with_multiple_args(), 6);
assert_eq!(boxed(Box::new({let x = 13; move || x})), 13);
assert_eq!(boxed_fn_once(Box::new({let x = 13; move || x})), 13);
box_dyn();
fn_item_as_closure_trait_object();
fn_item_with_args_as_closure_trait_object();
fn_item_with_multiple_args_as_closure_trait_object();
+145
View File
@@ -0,0 +1,145 @@
#![feature(unsized_locals)]
fn ref_box_dyn() {
struct Struct(i32);
trait Trait {
fn method(&self);
fn box_method(self: Box<Self>);
}
impl Trait for Struct {
fn method(&self) {
assert_eq!(self.0, 42);
}
fn box_method(self: Box<Self>) {
assert_eq!(self.0, 7);
}
}
struct Foo<T: ?Sized>(T);
let y: &dyn Trait = &Struct(42);
y.method();
let x: Foo<Struct> = Foo(Struct(42));
let y: &Foo<dyn Trait> = &x;
y.0.method();
let y: Box<dyn Trait> = Box::new(Struct(42));
y.method();
let y = &y;
y.method();
let y: Box<dyn Trait> = Box::new(Struct(7));
y.box_method();
}
fn box_box_trait() {
struct DroppableStruct;
static mut DROPPED: bool = false;
impl Drop for DroppableStruct {
fn drop(&mut self) {
unsafe { DROPPED = true; }
}
}
trait MyTrait { fn dummy(&self) { } }
impl MyTrait for Box<DroppableStruct> {}
struct Whatever { w: Box<dyn MyTrait+'static> }
impl Whatever {
fn new(w: Box<dyn MyTrait+'static>) -> Whatever {
Whatever { w: w }
}
}
{
let f = Box::new(DroppableStruct);
let a = Whatever::new(Box::new(f) as Box<dyn MyTrait>);
a.w.dummy();
}
assert!(unsafe { DROPPED });
}
fn unsized_dyn() {
pub trait Foo {
fn foo(self) -> String;
}
struct A;
impl Foo for A {
fn foo(self) -> String {
format!("hello")
}
}
let x = *(Box::new(A) as Box<dyn Foo>);
assert_eq!(x.foo(), format!("hello"));
// I'm not sure whether we want this to work
let x = Box::new(A) as Box<dyn Foo>;
assert_eq!(x.foo(), format!("hello"));
}
fn unsized_dyn_autoderef() {
pub trait Foo {
fn foo(self) -> String;
}
impl Foo for [char] {
fn foo(self) -> String {
self.iter().collect()
}
}
impl Foo for str {
fn foo(self) -> String {
self.to_owned()
}
}
impl Foo for dyn FnMut() -> String {
fn foo(mut self) -> String {
self()
}
}
let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>);
assert_eq!(&x.foo() as &str, "hello");
let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>;
assert_eq!(&x.foo() as &str, "hello");
let x = "hello".to_owned().into_boxed_str();
assert_eq!(&x.foo() as &str, "hello");
let x = *("hello".to_owned().into_boxed_str());
assert_eq!(&x.foo() as &str, "hello");
let x = "hello".to_owned().into_boxed_str();
assert_eq!(&x.foo() as &str, "hello");
let x = *(Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>);
assert_eq!(&x.foo() as &str, "hello");
let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
assert_eq!(&x.foo() as &str, "hello");
}
fn main() {
ref_box_dyn();
box_box_trait();
// "exotic" receivers
unsized_dyn();
unsized_dyn_autoderef();
}
-30
View File
@@ -1,30 +0,0 @@
struct Struct(i32);
trait Trait {
fn method(&self);
}
impl Trait for Struct {
fn method(&self) {
assert_eq!(self.0, 42);
}
}
struct Foo<T: ?Sized>(T);
fn main() {
let y: &dyn Trait = &Struct(42);
y.method();
let x: Foo<Struct> = Foo(Struct(42));
let y: &Foo<dyn Trait> = &x;
y.0.method();
let x: Box<dyn Fn(i32) -> i32> = Box::new(|x| x * 2);
assert_eq!(x(21), 42);
let mut i = 5;
{
let mut x: Box<dyn FnMut()> = Box::new(|| i *= 2);
x(); x();
}
assert_eq!(i, 20);
}