gccrs
gccrs copied to clipboard
Type error in to_le implementation
I tried this code:
fn to_le(this: u32) -> u32 {
#[cfg(target_endian = "little")]
{
this
}
#[cfg(not(target_endian = "little"))]
{
this.swap_bytes()
}
}
I expected to see this happen: Compiles
Instead, this happened:
<source>:3:5: error: expected [()] got [u32]
3 | {
| ^
<source>:1:1: error: expected [u32] got [()]
1 | fn to_le(this: u32) -> u32 {
| ^ ~
Compiler returned: 1
Meta
- What version of Rust GCC were you using, git sha if possible.
gccrs (Compiler-Explorer-Build-gcc-8809ee8c6a5621e830f3cfe66c381f986e63c7f2-binutils-2.38) 12.0.1 20220118 (experimental)
The reason for this is actually a bit weird. rustc
stores the content of blocks as a list of statements, while we keep a list of statements and a tail expression. When expanding and stripping our tail expression (like here on little-endian systems), this doesn't cause the previous statement to become the tail expression like it does on rustc, as shown by our AST pretty printer:
fn swap_bytes(this: u32) -> u32 {
this /* tail expr */
}
fn to_le(this: u32) -> u32 {
{
this /* tail expr */
}
; /* stmt */
{
swap_bytes(
this,
) /* tail expr */
}
/* tail expr */
}
fn swap_bytes(this: u32) -> u32 {
this /* tail expr */
}
fn to_le(this: u32) -> u32 {
{
this /* tail expr */
}
; /* stmt */
}
This explains the second error, where we expect the function to return a u32
but get the unit type as there is no tail expression.
Because of this, we also get the first typecheck error: If we were to compile the following code with rustc
fn swap_bytes(this: u32) -> u32 {
/* dummy */
this
}
fn to_le(this: u32) -> u32 {
{
this
}
{
swap_bytes(this)
}
}
we'd get a similar error, since the first block would be understood as a statement and not an expression:
error[E0308]: mismatched types
--> test-rustc.rs:8:9
|
8 | this
| ^^^^ expected `()`, found `u32`
|
help: you might have meant to return this value
|
8 | return this;
| ++++++ +
So the fix is in theory quite simple: Simply only keep a list of statements in our BlockExpr
type. However, unlike rustc
, our statements are not usable as expressions: only our expressions are usable as statements. So this is actually a really big change which is gonna be annoying to deal with.
@philberty, or anyone, if you have any thoughts before I investigate further or start fixing the issue let me know.
Fixed by #2156