Crystal: Can't cast union of pointers to union member type

Created on 12 May 2020  路  3Comments  路  Source: crystal-lang/crystal

Feels like this should have come up before but I couldn't find anything.

struct A
end

struct B
end

a = A.new
b = B.new

obj = rand == 0 ? a : b
obj.as(B)

ary = rand == 0 ? [a] : [b]
ary.as(Array(B))

ptr = rand == 0 ? pointerof(a) : pointerof(b)

ptr.as(B*)
Error: can't cast (Pointer(A) | Pointer(B)) to Pointer(B)

What am I missing? What makes the last case different than the other two?

bug compiler

Most helpful comment

This is the relevant code:

https://github.com/crystal-lang/crystal/blob/35c1f41f05144d9645c7bba83cd1b1deaea68fb0/src/compiler/crystal/semantic/cleanup_transformer.cr#L728-L734

In the language you can do:

class A
end

A.new.as(Void*)
A.new.as(Int8*)

You can basically cast any reference type to a pointer, because a reference is represented as a pointer. This is useful for some low level things.

You can't do that with structs. The compiler will complain.

You can then cast a pointer to another pointer.

But we forgot about being able to cast a union of pointers to a pointer. That use case or scenario never came to our minds.

Is that more clear?

All 3 comments

You can cast any reference type to pointer. But you can't cast a struct to a pointer. Im pretty sure we never though about casting a union of pointers to a pointer and the compiler is complaining because that's not a reference type.

It should be easy to fix.

I'm not sure I fully follow. A and B are both structs, obj is a union of both of them, yet the cast works?

This is the relevant code:

https://github.com/crystal-lang/crystal/blob/35c1f41f05144d9645c7bba83cd1b1deaea68fb0/src/compiler/crystal/semantic/cleanup_transformer.cr#L728-L734

In the language you can do:

class A
end

A.new.as(Void*)
A.new.as(Int8*)

You can basically cast any reference type to a pointer, because a reference is represented as a pointer. This is useful for some low level things.

You can't do that with structs. The compiler will complain.

You can then cast a pointer to another pointer.

But we forgot about being able to cast a union of pointers to a pointer. That use case or scenario never came to our minds.

Is that more clear?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sija picture Sija  路  3Comments

asterite picture asterite  路  3Comments

cjgajard picture cjgajard  路  3Comments

pbrusco picture pbrusco  路  3Comments

lbguilherme picture lbguilherme  路  3Comments