crystal icon indicating copy to clipboard operation
crystal copied to clipboard

Instance variable '@callback' of Foo must be (Proc((T | Nil)) | Nil), not Proc(Nil)

Open Sija opened this issue 9 years ago • 7 comments

Hi, I cannot wrap my head around below piece of code... What am I doing wrong? https://carc.in/#/r/16r0

Sija avatar Aug 10 '16 02:08 Sija

reduced

class Foo
  @callback : Proc(Bool?)? = -> {}
end

Error in line 2: instance variable '@callback' of Foo must be (Proc((Bool | Nil)) | Nil), not Proc(Nil)

lribeiro avatar Aug 10 '16 06:08 lribeiro

Right now, a proc that returns X isn't implicitly castable to a proc that returns X | Y.

In your case you have ->{}, which is Proc(Nil), but you require the callback to be Proc(Bool | Nil). It's solved if you do Proc(Bool?).new { } instead of ->{}.

I'm still not sure the rules should change. This works but maybe shouldn't:

def foo(block : -> Int32 | String)
end

foo ->{ 1 }

asterite avatar Aug 10 '16 13:08 asterite

IMO it makes sense that you can use Proc(X) as Proc(X | Y). What would be the downside of that? The returned value is of type X and thus can be assigned to X | Y. I'm not sure about implicit casting, but Proc(X).as(Proc(X | Y)) should be doable.

straight-shoota avatar Dec 01 '20 22:12 straight-shoota

The problem is that a proc doesn't know what type it returns, only the compiler knows this when generating the executable. So, if you have a Proc returning X, when you call it the compiler assumes it's X. If you assign a Proc that returns X to a Proc that returns X or Y, when you call it you get a value that's assumed to be X or Y, which has a different memory layout than X. Boom.

Casting between proc types is already possible: use a proc literal, call the other proc and cast the return value.

asterite avatar Dec 02 '20 01:12 asterite

@asterite Would it be possible for compiler to cast Proc(X) to Proc(X | Y) by appending .as call?

Sija avatar Dec 02 '20 19:12 Sija

as doesn't work, I was just saying there's a way to fake it. And no, these casts will never be done

asterite avatar Dec 02 '20 19:12 asterite

This issue has been mentioned on Crystal Forum. There might be relevant details there:

https://forum.crystal-lang.org/t/outsmarted-by-the-compiler/8051/3

crysbot avatar May 12 '25 20:05 crysbot