`macro-issue1233.rs` is broken on big-endian systems
The issue probably comes to how we perform cfg expansion in blocks, regarding statements and final expressions. Here is a test case failing as well on LE systems.
// { dg-additional-options "-w" }
macro_rules! impl_uint {
($($ty:ident = $lang:literal),*) => {
$(
impl $ty {
pub fn to_le(self) -> Self {
#[cfg(not(target_endian = "big"))]
{
self
}
#[cfg(target_endian = "big")]
{
self
}
}
}
)*
}
}
impl_uint!(u8 = "u8", u16 = "u16", u32 = "u32");
The order of the "blocks + cfg" in the test case matter, which means that what is probably happening is we are parsing the first block + cfg as a statement. When the second block + cfg gets removed, due to the predicate not being met, we end up with a statement and no return expression. So the function gets a Self as a statement, ignores that, returns a (), and we get a type error.
And for an example that rustc can compile without complaining about redefining primitive items:
// { dg-additional-options "-w" }
macro_rules! impl_uint {
($($ty:ident = $lang:literal),*) => {
$(
struct $ty;
impl $ty {
pub fn to_le(self) -> Self {
#[cfg(not(target_endian = "big"))]
{
self
}
#[cfg(target_endian = "big")]
{
self
}
}
}
)*
}
}
impl_uint!(z1 = "z1", z16 = "z16", z12 = "z12");
The corresponding struct in rustc simply contains one Vec<Stmt> and no optional tail expression: https://github.com/rust-lang/rust/blob/77972d2d0134fb597249b3b64dcf9510a790c34e/compiler/rustc_ast/src/ast.rs#L567-L583
This should be fixed by #2156 as well