From 9542188fa29853159a27a6f272af5b3497d592ae Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Mon, 11 Feb 2019 16:17:10 +0100 Subject: [PATCH] Update `vec!` to have the same coercion behavior as arrays Before this commit, `vec![a, b, c]` had different coercion behavior than the array `[a, b, c]`. Example: fn foo() {} fn bar() {} let arr = [foo, bar]; // works, fn items coerced to fn pointer let v = vec![foo, bar]; // doesn't work Last line results in: error[E0308]: mismatched types --> src/main.rs:6:13 | 6 | let v = vec![foo, bar]; // doesn't work | ^^^^^^^^^^^^^^ expected slice, found array of 2 elements | = note: expected type `std::boxed::Box<[fn() {main::foo}]>` found type `std::boxed::Box<[fn(); 2]>` This is due to `box [a, b, c]` behaving a bit strangely. A very related question on StackOverflow: https://stackoverflow.com/q/54632524/2408867 By introducing this temporary let binding, we can fix the coercion behavior. I'm pretty sure this is not a breaking change as it only allows more cases to compile. --- src/liballoc/macros.rs | 17 ++++++++++++++--- src/liballoc/tests/vec.rs | 8 ++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index db91b07fa71b4..ee2f12df8baa3 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -39,9 +39,20 @@ macro_rules! vec { ($elem:expr; $n:expr) => ( $crate::vec::from_elem($elem, $n) ); - ($($x:expr),*) => ( - <[_]>::into_vec(box [$($x),*]) - ); + ($($x:expr),*) => ({ + // We use a temporary let binding to work around a coercion + // bug/strangness with `box [a, b]` syntax. Example: + // + // fn foo() {} + // fn bar() {} + // + // let _ = [foo, bar]; // works: fn items coerced to fn pointers + // let _ = <[_]>::into_vec(box [foo, bar]); // doesn't work + // + // See the `macro_fn_pointer_coercion` test. + let tmp = [$($x),*]; + <[_]>::into_vec(box tmp) + }); ($($x:expr,)*) => (vec![$($x),*]) } diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 545332bcd6a2f..8f01f6360b6aa 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1151,3 +1151,11 @@ fn test_try_reserve_exact() { } } + +#[test] +fn macro_fn_pointer_coercion() { + fn foo() {} + fn bar() {} + + let _v = vec![foo, bar]; +}