I wrote a macro to avoid repeating boilerplate for a bunch of related From
impls:
struct CStrV {
v: *const *const u8
}
impl CStrV {
fn new(v: *const *const u8) -> Self { Self { v } }
// etc
}
macro_rules! cstrv_from {
($ty:ty) => {
impl From<$ty> for CStrV {
fn from(v: $ty) -> CStrV {
CStrV::new(v)
}
}
};
($ty:ty, $conv:expr) => {
impl From<$ty> for CStrV {
fn from(v: $ty) -> CStrV {
CStrV::new($conv(v))
}
}
};
}
cstrv_from! { *const *const u8 }
cstrv_from! { *const *mut u8, |v| v.cast::<*const u8>() }
cstrv_from! { *mut *const u8, |v| v.cast_const() }
cstrv_from! { *mut *mut u8, |v| v.cast::<*const u8>().cast_const() }
This doesn't compile, demanding type annotations for the conversion closures:
error[E0282]: type annotations needed
--> src/lib.rs:26:33
|
26 | cstrv_from! { *const *mut u8, |v| v.cast::<*const u8>() }
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
26 | cstrv_from! { *const *mut u8, |v: /* Type */| v.cast::<*const u8>() }
| ++++++++++++
I thought it was the macro's fault, but I get the same error if I manually expand the macro, e.g.
impl From<*mut *const u8> for CStrV {
fn from(v: *mut *const u8) -> CStrV {
CStrV::new((|w| w.cast_const())(v))
}
}
The required argument type should be trivially inferrable; why won't the compiler do it in this particular context?
... This is a semi-XY situation; I'm only using closures in the first place because the rules for intertwingling tokens from macro body and macro arguments won't let me do this instead
macro_rules! cstrv_from {
($ty:ty) => {
impl From<$ty> for CStrV {
fn from(v: $ty) -> CStrV {
CStrV::new(v)
}
}
};
($ty:ty, $conv:expr) => {
impl From<$ty> for CStrV {
fn from(v: $ty) -> CStrV {
CStrV::new(v.$conv)
}
}
};
}
cstrv_from! { *const *const u8 }
cstrv_from! { *const *mut u8, cast::<*const u8>() }
cstrv_from! { *mut *const u8, cast_const() }
cstrv_from! { *mut *mut u8, cast::<*const u8>().cast_const() }
so if anyone knows how to make something like that Do What I Meant, that'd be even better.