rust/tests/run-pass/dyn-traits.rs

141 lines
2.9 KiB
Rust

#![feature(unsized_locals)]
fn ref_dyn() {
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);
let y: &dyn Trait = &Struct(42);
y.method();
let x: Foo<Struct> = Foo(Struct(42));
let y: &Foo<dyn Trait> = &x;
y.0.method();
}
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 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_dyn();
box_dyn();
box_box_trait();
// "exotic" receivers
unsized_dyn();
unsized_dyn_autoderef();
}