+++ /dev/null
-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 }
- }
-}
-
-fn main() {
- {
- let f = Box::new(DroppableStruct);
- let a = Whatever::new(Box::new(f) as Box<dyn MyTrait>);
- a.w.dummy();
- }
- assert!(unsafe { DROPPED });
-}
--- /dev/null
+#![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();
+}