rust/tests/pass/dyn-traits.rs
2022-06-01 10:53:38 -04:00

147 lines
3.0 KiB
Rust

#![feature(unsized_locals, unsized_fn_params)]
#![allow(incomplete_features)]
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();
}