It looks like it's about binding a type constructor to a variable, but I haven't seen in in a wild and compiler accepts it like it's normal. So that's why I'm asking.
Thanks in advance!
link to playgroud
#[derive(Debug)]
struct B(u8);
#[derive(Debug)]
enum E {
A(u8),
}
fn main() {
let y = E::A;
let y = y(0);
dbg!(y);
let x = B;
let x = x(0);
dbg!(x);
// uncomment to see compiler complain
// let c: fn(u8) -> u8 = B;
}
UPD: Just recalled what made me curious. It's code block from Rust 1.66.0 Announce, which I also find very confusing.
#[repr(u8)]
enum Foo {
A(u8),
B(i8),
C(bool) = 42,
}
They behave like that because the compiler is designed that way.
Tuple-like structs and tuple-like enum variants can both be used as zero-sized values of their respective function item type.
And those, in turn, can be coerced into function pointers, which is what c
is declared as when you assign a type of fn(_) -> _
.
This is documented here: The Rust Reference - Function item types.
For tuple structs & enum variants the compiler will define a function with the same name as the struct/variant for convenience. It allows for easy wrapping of collections in a struct / variant like this:
let ints = vec![1u8, 2, 3, 4];
let bs = ints.iter().copied().map(B).collect::<Vec<_>>();
let as = ints.iter().copied().map(E::A).collect::<Vec<_>>();
It's probably also there to avoid confusion where one can just omit the parentheses for some identifiers but not for others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With