~sircmpwn/hare-users

8 3

Match a pointer to tagged union

Details
Message ID
<20221213105620.270b34ef@denis-laptop>
DKIM signature
pass
Download raw message
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
Details
Message ID
<CAG3idSdZ85Fa7Vgixe7VSb2aJzfip_2FO-Ya9VgfELejQ5k15w@mail.gmail.com>
In-Reply-To
<20221213105620.270b34ef@denis-laptop> (view parent)
DKIM signature
pass
Download raw message
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
Details
Message ID
<20221213130721.6b052e6c@denis-laptop>
In-Reply-To
<CAG3idSdZ85Fa7Vgixe7VSb2aJzfip_2FO-Ya9VgfELejQ5k15w@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
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
Details
Message ID
<CAG3idSfQeakmQUJSawzoxn0JqE7xKGZVzMYikhMKqkWuPDFLXA@mail.gmail.com>
In-Reply-To
<20221213130721.6b052e6c@denis-laptop> (view parent)
DKIM signature
pass
Download raw message
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
Details
Message ID
<CP0UM16406NE.38BBBPAP5Z0F@eiger>
In-Reply-To
<CAG3idSfQeakmQUJSawzoxn0JqE7xKGZVzMYikhMKqkWuPDFLXA@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
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.
Details
Message ID
<CAG3idSf0xbPUWtJ06+YrVRJZ366Y-tcPi35uGQjnu5noXObfhQ@mail.gmail.com>
In-Reply-To
<CP0UM16406NE.38BBBPAP5Z0F@eiger> (view parent)
DKIM signature
pass
Download raw message
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?
Details
Message ID
<20221213205223.62bd9081@denis-laptop>
In-Reply-To
<CAG3idSf0xbPUWtJ06+YrVRJZ366Y-tcPi35uGQjnu5noXObfhQ@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
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
Details
Message ID
<CP0YC47O9MX9.3LS42BI26RAZ@eiger>
In-Reply-To
<CAG3idSf0xbPUWtJ06+YrVRJZ366Y-tcPi35uGQjnu5noXObfhQ@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
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.
Details
Message ID
<CAG3idSfpyYi1zAF6urHSKnt7vUT-rJMcPYv7FvXv40o=FwMDvA@mail.gmail.com>
In-Reply-To
<CP0YC47O9MX9.3LS42BI26RAZ@eiger> (view parent)
DKIM signature
pass
Download raw message
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.
Reply to thread Export thread (mbox)