Closed paulbutcher closed 1 year ago
Is this "new" or old?
Not sure yet.
OK, this is very curious. It works just fine when run like this:
java -jar flix.jar run
1
But not when run from the REPL:
java -jar flix.jar
__ _ _
/ _| | | (_) Welcome to Flix v0.34.0
| |_ | | _ __ __
| _| | | | | \ \/ / Enter an expression to have it evaluated.
| | | | | | > < Type ':help' for more information.
|_| |_| |_| /_/\_\ Type ':quit' or press 'ctrl + d' to exit.
flix> :eval main()
java.lang.ClassCastException: class List%Nil%Obj cannot be cast to class dev.flix.runtime.Unit (List%Nil%Obj and dev.flix.runtime.Unit are in unnamed module of loader ca.uwaterloo.flix.language.phase.jvm.FlixClassLoader @701a32)
at Def%main%.invoke(Unknown Source)
at Cont%Obj.unwind(Cont%Obj)
at Ns.m_main%(Unknown Source)
at Main.main(Main)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.mainFunction$1(Bootstrap.scala:79)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9(Bootstrap.scala:88)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9$adapted(Bootstrap.scala:88)
at ca.uwaterloo.flix.runtime.shell.Shell.run(Shell.scala:384)
at ca.uwaterloo.flix.runtime.shell.Shell.execEval(Shell.scala:311)
at ca.uwaterloo.flix.runtime.shell.Shell.execReloadAndEval(Shell.scala:326)
at ca.uwaterloo.flix.runtime.shell.Shell.execute(Shell.scala:173)
at ca.uwaterloo.flix.runtime.shell.Shell.loop(Shell.scala:124)
at ca.uwaterloo.flix.tools.SimpleRunner$.run(SimpleRunner.scala:62)
at ca.uwaterloo.flix.Main$.main(Main.scala:125)
at ca.uwaterloo.flix.Main.main(Main.scala)
Not immediately sure what to make of that 🤔
And it seems to have been introduced somewhere between 0.32.0 and 0.33.0
I think I may need some help from someone who understands code generation better than I do, as I'm not really sure how to get started with this. This is the simplest form I've found which reproduces the error:
def recvWithDefault(rx: Receiver[Int32, r]): Int32 \ { Read(r), Write(r) } =
select {
case x <- Channel.recv(rx) => x
case _ => 1
}
def main(): Int32 \ IO =
let (_, rx) = Channel.buffered(Static, 1);
recvWithDefault(rx)
In particular, this, which on the face of things should behave identically, doesn't reproduce the error:
def main(): Int32 \ IO =
let (_, rx) = Channel.buffered(Static, 1);
select {
case x <- Channel.recv(rx) => x
case _ => 1
}
@mlutze do you have any insight?
OK, so the shell wraps main
up in an unsafe_cast
and println
. If I bring that in, then I can see the error without the REPL:
def recvWithDefault(rx: Receiver[Int32, r]): Int32 \ { Read(r), Write(r) } =
select {
case x <- Channel.recv(rx) => x
case _ => 1
}
def mainx(): Int32 \ IO =
let (_, rx) = Channel.buffered(Static, 1);
recvWithDefault(rx)
def main(): Unit \ IO =
unsafe_cast println(mainx()) as \ IO
java -jar flix.jar run
java.lang.ClassCastException: class List%Nil%Obj cannot be cast to class dev.flix.runtime.Unit (List%Nil%Obj and dev.flix.runtime.Unit are in unnamed module of loader ca.uwaterloo.flix.language.phase.jvm.FlixClassLoader @46f699d5)
at Def%main%.invoke(Unknown Source)
at Cont%Obj.unwind(Cont%Obj)
at Ns.m_main%(Unknown Source)
at Main.main(Main)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.mainFunction$1(Bootstrap.scala:79)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9(Bootstrap.scala:88)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9$adapted(Bootstrap.scala:88)
at ca.uwaterloo.flix.tools.Packager$.$anonfun$run$2(Packager.scala:321)
at scala.Option.map(Option.scala:242)
at ca.uwaterloo.flix.tools.Packager$.$anonfun$run$1(Packager.scala:319)
at scala.Option.flatMap(Option.scala:283)
at ca.uwaterloo.flix.tools.Packager$.run(Packager.scala:318)
at ca.uwaterloo.flix.Main$.main(Main.scala:149)
at ca.uwaterloo.flix.Main.main(Main.scala)
So I guess that means that what's actually returned from mainx
in this case is a List%Nil%Obj
, not Unit
? But I don't really know where to go looking for the error (or even whether it is an error for it to be doing so)?
I've seen this before somewhere but I cannot remember what the context was 🤔
Oh here https://github.com/flix/flix/issues/4840, not that I know what the issue is. I can take a dive in the bytecode later
@paulbutcher does it still persist if you disable the optimizer? (maybe that has to be done in code)
@paulbutcher does it still persist if you disable the optimizer? (maybe that has to be done in code)
No, disabling the optimiser makes no difference:
java -jar flix.jar run --Xno-optimizer
java.lang.ClassCastException: class List%Nil%Obj cannot be cast to class dev.flix.runtime.Unit (List%Nil%Obj and dev.flix.runtime.Unit are in unnamed module of loader ca.uwaterloo.flix.language.phase.jvm.FlixClassLoader @4c51bb7)
at Def%recvWithDefault%141262.invoke(Unknown Source)
at Cont%Int32.unwind(Cont%Int32)
at Def%main.invoke(Unknown Source)
at Cont%Obj.unwind(Cont%Obj)
at Def%main%.invoke(Unknown Source)
at Cont%Obj.unwind(Cont%Obj)
at Ns.m_main%(Unknown Source)
at Main.main(Main)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.mainFunction$1(Bootstrap.scala:79)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9(Bootstrap.scala:88)
at ca.uwaterloo.flix.language.phase.jvm.Bootstrap$.$anonfun$bootstrap$9$adapted(Bootstrap.scala:88)
at ca.uwaterloo.flix.tools.Packager$.$anonfun$run$2(Packager.scala:321)
at scala.Option.map(Option.scala:242)
at ca.uwaterloo.flix.tools.Packager$.$anonfun$run$1(Packager.scala:319)
at scala.Option.flatMap(Option.scala:283)
at ca.uwaterloo.flix.tools.Packager$.run(Packager.scala:318)
at ca.uwaterloo.flix.Main$.main(Main.scala:149)
at ca.uwaterloo.flix.Main.main(Main.scala)
The error is in the generated match error case of select (in the generated code, not saying that's the source of the issue)
if (0 == var12) {
IList%Obj var14 = (IList%Obj)var13;
Def%unsafeGetAndUnlock%141564 var26 = new Def%unsafeGetAndUnlock%141564();
var26.arg0 = (IMpmc%Int32)var10;
var26.arg1 = (IList%Obj)var14;
int var15 = var26.unwind();
var27 = var15;
} else {
int var16 = ((Tuple2%Int32%Obj)var11).field0;
Unit var17 = (Unit)((Tuple2%Int32%Obj)var11).field1;
if (-1 != var16) {
throw new MatchError(new ReifiedSourceLocation("main\\src\\personal\\test.flix", 2, 5, 5, 6));
}
var27 = 1;
}
Thanks for chipping in @JonathanStarup
The following:
Gives: