3 The tracking issue for this feature is: [#48055]
5 [#48055]: https://github.com/rust-lang/rust/issues/48055
7 ------------------------
9 This implements [RFC1909]. When turned on, you can have unsized arguments and locals:
11 [RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-coercions.md
14 #![feature(unsized_locals)]
19 let x: Box<dyn Any> = Box::new(42);
21 // ^ unsized local variable
22 // ^^ unsized temporary
27 // ^^^^^^ unsized argument
30 The RFC still forbids the following unsized expressions:
33 #![feature(unsized_locals)]
37 struct MyStruct<T: ?Sized> {
41 struct MyTupleStruct<T: ?Sized>(T);
43 fn answer() -> Box<dyn Any> {
48 // You CANNOT have unsized statics.
49 static X: dyn Any = *answer(); // ERROR
50 const Y: dyn Any = *answer(); // ERROR
52 // You CANNOT have struct initialized unsized.
53 MyStruct { content: *answer() }; // ERROR
54 MyTupleStruct(*answer()); // ERROR
55 (42, *answer()); // ERROR
57 // You CANNOT have unsized return types.
58 fn my_function() -> dyn Any { *answer() } // ERROR
60 // You CAN have unsized local variables...
61 let mut x: dyn Any = *answer(); // OK
62 // ...but you CANNOT reassign to them.
63 x = *answer(); // ERROR
65 // You CANNOT even initialize them separately.
67 y = *answer(); // ERROR
69 // Not mentioned in the RFC, but by-move captured variables are also Sized.
70 let x: dyn Any = *answer();
75 // You CAN create a closure with unsized arguments,
76 // but you CANNOT call it.
77 // This is an implementation detail and may be changed in the future.
78 let f = |x: dyn Any| {};
79 f(*answer()); // ERROR
83 However, the current implementation allows `MyTupleStruct(..)` to be unsized. This will be fixed in the future.
85 ## By-value trait objects
87 With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
90 #![feature(unsized_locals)]
96 impl<T: ?Sized> Foo for T {}
99 let slice: Box<[i32]> = Box::new([1, 2, 3]);
100 <[i32] as Foo>::foo(*slice);
104 And `Foo` will also be object-safe. However, this object-safety is not yet implemented.
107 #![feature(unsized_locals)]
113 impl<T: ?Sized> Foo for T {}
116 let slice: Box<dyn Foo> = Box::new([1, 2, 3]);
117 // doesn't compile yet
118 <dyn Foo as Foo>::foo(*slice);
122 Unfortunately, this is not implemented yet.
124 One of the objectives of this feature is to allow `Box<dyn FnOnce>`, instead of `Box<dyn FnBox>` in the future. See [#28796] for details.
126 [#28796]: https://github.com/rust-lang/rust/issues/28796
128 ## Variable length arrays
130 The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`.
133 #![feature(unsized_locals)]
135 fn mergesort<T: Ord>(a: &mut [T]) {
136 let mut tmp = [T; dyn a.len()];
141 let mut a = [3, 1, 5, 6];
143 assert_eq!(a, [1, 3, 5, 6]);
147 VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`.
149 ## Advisory on stack usage
151 It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are:
153 - When you need a by-value trait objects.
154 - When you really need a fast allocation of small temporary arrays.
156 Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code
159 #![feature(unsized_locals)]
162 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
163 let _x = {{{{{{{{{{*x}}}}}}}}}};
170 #![feature(unsized_locals)]
174 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
180 will unnecessarily extend the stack frame.