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-unsized-rvalues.md
14 #![allow(incomplete_features)]
15 #![feature(unsized_locals, unsized_fn_params)]
20 let x: Box<dyn Any> = Box::new(42);
22 // ^ unsized local variable
23 // ^^ unsized temporary
28 // ^^^^^^ unsized argument
31 The RFC still forbids the following unsized expressions:
34 #![feature(unsized_locals)]
38 struct MyStruct<T: ?Sized> {
42 struct MyTupleStruct<T: ?Sized>(T);
44 fn answer() -> Box<dyn Any> {
49 // You CANNOT have unsized statics.
50 static X: dyn Any = *answer(); // ERROR
51 const Y: dyn Any = *answer(); // ERROR
53 // You CANNOT have struct initialized unsized.
54 MyStruct { content: *answer() }; // ERROR
55 MyTupleStruct(*answer()); // ERROR
56 (42, *answer()); // ERROR
58 // You CANNOT have unsized return types.
59 fn my_function() -> dyn Any { *answer() } // ERROR
61 // You CAN have unsized local variables...
62 let mut x: dyn Any = *answer(); // OK
63 // ...but you CANNOT reassign to them.
64 x = *answer(); // ERROR
66 // You CANNOT even initialize them separately.
68 y = *answer(); // ERROR
70 // Not mentioned in the RFC, but by-move captured variables are also Sized.
71 let x: dyn Any = *answer();
76 // You CAN create a closure with unsized arguments,
77 // but you CANNOT call it.
78 // This is an implementation detail and may be changed in the future.
79 let f = |x: dyn Any| {};
80 f(*answer()); // ERROR
84 ## By-value trait objects
86 With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
89 #![feature(unsized_fn_params)]
95 impl<T: ?Sized> Foo for T {}
98 let slice: Box<[i32]> = Box::new([1, 2, 3]);
99 <[i32] as Foo>::foo(*slice);
103 And `Foo` will also be object-safe.
106 #![feature(unsized_fn_params)]
112 impl<T: ?Sized> Foo for T {}
115 let slice: Box<dyn Foo> = Box::new([1, 2, 3]);
116 // doesn't compile yet
117 <dyn Foo as Foo>::foo(*slice);
121 One of the objectives of this feature is to allow `Box<dyn FnOnce>`.
123 ## Variable length arrays
125 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]`.
127 ```rust,ignore (not-yet-implemented)
128 #![feature(unsized_locals)]
130 fn mergesort<T: Ord>(a: &mut [T]) {
131 let mut tmp = [T; dyn a.len()];
136 let mut a = [3, 1, 5, 6];
138 assert_eq!(a, [1, 3, 5, 6]);
142 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]`.
144 ## Advisory on stack usage
146 It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are:
148 - When you need a by-value trait objects.
149 - When you really need a fast allocation of small temporary arrays.
151 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
154 #![feature(unsized_locals)]
157 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
158 let _x = {{{{{{{{{{*x}}}}}}}}}};
165 #![feature(unsized_locals)]
169 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
175 will unnecessarily extend the stack frame.