Hello,
I'm learning and playing a little with Hare, and I get this error:
```
Abort: /home/denis/hare/main.ha:28:1: execution reached
unreachable code (compiler bug)
```
I'm not sure if it is really a compiler bug, or if I do something
wrong. Is this piece of code valid?
```
use fmt;
type a = struct {
i: int,
};
type b = struct {
j: int,
};
type z = (a | b);
export fn main() void = {
fmt::printfln("hey")!;
let x = a {
i = 10,
};
let y = b {
j = 32
};
print(&x: *z);
};
fn print(e: *z) void = {
match (*e) {
case let e: a =>
fmt::printfln("a: {}", e.i)!;
case let e: b =>
fmt::printfln("b: {}", e.j)!;
};
};
```
Thank you in advance,
thank you for Hare, it is fun to learn a low-level language again,
Denis
Welcome to Hare!
This is a known issue, but easily worked around: simply add a default
case in your match expression, as follows.
```
use fmt;
type a = struct {
i: int,
};
type b = struct {
j: int,
};
type z = (a | b);
export fn main() void = {
fmt::printfln("hey")!;
let x = a {
i = 10,
};
let y = b {
j = 32
};
print(&x: *z);
};
fn print(e: *z) void = {
match (*e) {
case let e: a =>
fmt::printfln("a: {}", e.i)!;
case let e: b =>
fmt::printfln("b: {}", e.j)!;
case => void;
};
};
```
Le mar. 13 déc. 2022 à 10:53, denis <denis@ecaf.be> a écrit :
>> Hello,>> I'm learning and playing a little with Hare, and I get this error:>> ```> Abort: /home/denis/hare/main.ha:28:1: execution reached> unreachable code (compiler bug)>> ```>> I'm not sure if it is really a compiler bug, or if I do something> wrong. Is this piece of code valid?>>> ```> use fmt;>> type a = struct {> i: int,> };>> type b = struct {> j: int,> };>> type z = (a | b);>> export fn main() void = {> fmt::printfln("hey")!;>> let x = a {> i = 10,> };> let y = b {> j = 32> };>> print(&x: *z);>> };>> fn print(e: *z) void = {> match (*e) {> case let e: a =>> fmt::printfln("a: {}", e.i)!;> case let e: b =>> fmt::printfln("b: {}", e.j)!;> };> };> ```>> Thank you in advance,> thank you for Hare, it is fun to learn a low-level language again,>> Denis
Hello,
> Welcome to Hare!
Thank you :)
> This is a known issue, but easily worked around: simply add a default> case in your match expression, as follows.
I just tried, and now everything go to the default case... So I can't
use the struct.
Is there a way to achieve that?
Thank you for the quick response,
Denis
Le mar. 13 déc. 2022 à 13:04, denis <denis@ecaf.be> a écrit :
>> Hello,>> > Welcome to Hare!>> Thank you :)>> > This is a known issue, but easily worked around: simply add a default> > case in your match expression, as follows.>> I just tried, and now everything go to the default case... So I can't> use the struct.>> Is there a way to achieve that?
AFAICT your conversion line 23 is invalid, as the internal representation of
a tagged union does not match the one for the a or b types (it has a u32 tag
in front I believe). Maybe the compiler should detect that.
The following, obviously, works:
```
use fmt;
type a = struct {
i: int,
};
type b = struct {
j: int,
};
type z = (a | b);
export fn main() void = {
fmt::printfln("hey")!;
let x = a {
i = 10,
};
let y = b {
j = 32
};
print(x);
};
fn print(e: z) void = {
match (e) {
case let e: a =>
fmt::printfln("a: {}", e.i)!;
case let e: b =>
fmt::printfln("b: {}", e.j)!;
case => void;
};
};
```
>> Thank you for the quick response,> Denis
On Tue Dec 13, 2022 at 2:25 PM UTC, Pierre Curto wrote:
> AFAICT your conversion line 23 is invalid, as the internal representation of> a tagged union does not match the one for the a or b types (it has a u32 tag> in front I believe). Maybe the compiler should detect that.
No, &a: *b is used to get around the compiler's safety checks around
conversions - it's similar to how if you cast an array to *[*]t and do
an out-of-bounds access, you'll get a segfault.
Le mar. 13 déc. 2022 à 17:59, Ember Sawady <ecs@d2evs.net> a écrit :
>> On Tue Dec 13, 2022 at 2:25 PM UTC, Pierre Curto wrote:> > AFAICT your conversion line 23 is invalid, as the internal representation of> > a tagged union does not match the one for the a or b types (it has a u32 tag> > in front I believe). Maybe the compiler should detect that.>> No, &a: *b is used to get around the compiler's safety checks around> conversions - it's similar to how if you cast an array to *[*]t and do> an out-of-bounds access, you'll get a segfault.
Yes, but then why does the match fail to see the a and b types?
Hello,
Thanks to your response, I found a solution:
```
let x = a {
i = 10,
};
let p: z = x;
print(&p);
```
or in one line:
```
print(&(x: z));
``
This works well, even without the "default case" in the switch.
I'm not sure if there is a problem with the compiler, it is too
technical for me...
Thank you,
Best regards,
Denis
Er, in my previous email, I meant to say *(&a: *b), but the point still
stands: we can't special-case a dereference and only drop the safety
checks there.
On Tue Dec 13, 2022 at 7:04 PM UTC, Pierre Curto wrote:
> Yes, but then why does the match fail to see the a and b types?
The first 32 bits of x are 10, so when that bit of memory is interpreted
as a tagged union (of type z), the tag ends up being 10. This isn't the
tag for either a or b, so neither of the match cases are taken. The
right thing to do here would be &(x: z) - casts to tagged unions have
special logic to make sure that everything works. By doing a pointer
cast instead, you're deliberately bypassing the compiler's safety
checks, and all bets are off.
Thanks for the explanation!
Le mar. 13 déc. 2022 à 20:54, Ember Sawady <ecs@d2evs.net> a écrit :
>> Er, in my previous email, I meant to say *(&a: *b), but the point still> stands: we can't special-case a dereference and only drop the safety> checks there.>> On Tue Dec 13, 2022 at 7:04 PM UTC, Pierre Curto wrote:> > Yes, but then why does the match fail to see the a and b types?>> The first 32 bits of x are 10, so when that bit of memory is interpreted> as a tagged union (of type z), the tag ends up being 10. This isn't the> tag for either a or b, so neither of the match cases are taken. The> right thing to do here would be &(x: z) - casts to tagged unions have> special logic to make sure that everything works. By doing a pointer> cast instead, you're deliberately bypassing the compiler's safety> checks, and all bets are off.