#861 compiler: fix Obj to Void coercion bug

alena Fri 11 Dec 2009

Hi guys,

Running this code:

class A
{
  Void foo()            // Method without return value
  {
    Obj res := "foo"
    return res          // Trying to return object (!!!)
                        // Obviously this is an error 
                        // but compiler doesn't generate 
                        // any error report
  }  
  static Void main()
  {
    A.make.foo
  }
}

I've got following exception:

sys::Err: java.lang.NoClassDefFoundError: V
  test::A.foo (A.fan:6)
  test::A.main (A.fan:11)
  java.lang.reflect.Method.invoke (Unknown)
  fan.sys.Method.invoke (Method.java:536)
  fan.sys.Method$MethodFunc.callList (Method.java:182)
  fan.sys.Method.callList (Method.java:147)
  fanx.tools.Fan.callMain (Fan.java:136)
  fanx.tools.Fan.executeType (Fan.java:103)
  fanx.tools.Fan.execute (Fan.java:39)
  fanx.tools.Fan.run (Fan.java:242)
  fanx.tools.Fan.main (Fan.java:280)

This bug cannot be reproduced by returning another type except Obj. So it seems like the reason why compiler doesn't report any error is that Void can be casted to Obj.

While investigating this problem I managed to get following stack trace:

java.lang.IllegalStateException: Register 7 V
        at fanx.emit.FCodeEmit.storeVar(FCodeEmit.java:573)
        at fanx.emit.FCodeEmit.storeVar(FCodeEmit.java:542)
        at fanx.emit.FCodeEmit.emitInstructions(FCodeEmit.java:89)
        at fanx.emit.FCodeEmit.emit(FCodeEmit.java:59)
        at fanx.emit.FMethodEmit.doEmit(FMethodEmit.java:386)
        at fanx.emit.FMethodEmit.emitStandard(FMethodEmit.java:65)
        at fanx.emit.FTypeEmit.emit(FTypeEmit.java:197)
        at fanx.emit.FTypeEmit.emit(FTypeEmit.java:100)
        at fanx.emit.FTypeEmit.emit(FTypeEmit.java:70)
        at fanx.emit.FTypeEmit.emitAndLoad(FTypeEmit.java:31)
        at fan.sys.ClassType.emit(ClassType.java:495)
        at fan.sys.FanClassLoader.findClass(FanClassLoader.java:192)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
        at java.lang.Class.getDeclaredFields0(Native Method)
        at java.lang.Class.privateGetDeclaredFields(Unknown Source)
        at java.lang.Class.getDeclaredFields(Unknown Source)
        at fan.sys.ClassType.finishSlots(ClassType.java:591)
        at fan.sys.ClassType.finish(ClassType.java:554)
        at fan.sys.Method$MethodFunc.isStatic(Method.java:459)
        at fan.sys.Method$MethodFunc.callList(Method.java:175)
        at fan.sys.Type.make(Type.java:242)
        at fan.sys.ClassType.make(ClassType.java:112)
        at fan.sys.Type.make(Type.java:232)
        at fanx.tools.Fant.runTest(Fant.java:154)
        at fanx.tools.Fant.test(Fant.java:92)
        at fanx.tools.Fant.test(Fant.java:28)
        at fanx.tools.Fant.run(Fant.java:255)
        at fanx.tools.Fant.main(Fant.java:292)
sys::Err: Cannot emit: codeanalysis::TreeBuilder
        at fan.sys.Err.make(Err.java:78)
        at fan.sys.Err.make(Err.java:68)
        at fan.sys.ClassType.emit(ClassType.java:503)
        at fan.sys.FanClassLoader.findClass(FanClassLoader.java:192)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
        at java.lang.Class.getDeclaredFields0(Native Method)
        at java.lang.Class.privateGetDeclaredFields(Unknown Source)
        at java.lang.Class.getDeclaredFields(Unknown Source)
        at fan.sys.ClassType.finishSlots(ClassType.java:591)
        at fan.sys.ClassType.finish(ClassType.java:554)
        at fan.sys.Method$MethodFunc.isStatic(Method.java:459)
        at fan.sys.Method$MethodFunc.callList(Method.java:175)
        at fan.sys.Type.make(Type.java:242)
        at fan.sys.ClassType.make(ClassType.java:112)
        at fan.sys.Type.make(Type.java:232)
        at fanx.tools.Fant.runTest(Fant.java:154)
        at fanx.tools.Fant.test(Fant.java:92)
        at fanx.tools.Fant.test(Fant.java:28)
        at fanx.tools.Fant.run(Fant.java:255)
        at fanx.tools.Fant.main(Fant.java:292)

ERROR: Cannot make test codeanalysis::EBnfGrammarTests
sys::Err: Method not mapped to java.lang.reflect correctly codeanalysis::EBnfGrammarTests.make
  fan.sys.Method$MethodFunc.isStatic (Method.java:466)
  fan.sys.Method$MethodFunc.callList (Method.java:175)
  fan.sys.Type.make (Type.java:242)
  fan.sys.ClassType.make (ClassType.java:112)
  fan.sys.Type.make (Type.java:232)
  fanx.tools.Fant.runTest (Fant.java:154)
  fanx.tools.Fant.test (Fant.java:92)
  fanx.tools.Fant.test (Fant.java:28)
  fanx.tools.Fant.run (Fant.java:255)
  fanx.tools.Fant.main (Fant.java:292)

Thanks!

tactics Fri 11 Dec 2009

Interesting. Looks like Obj is getting auto-downcasted to Void.

DanielFath Fri 11 Dec 2009

Yeah, but it makes sense when you think about Void as a class (I can replace return type Void with Bool and it would behave in the same way). Should that even be corrected, or should returning a Void be a special case?

tactics Fri 11 Dec 2009

Oh, it's definitely an error. Void is handled as a special case, just like in Java. It's not like ML's unit type.

brian Sat 12 Dec 2009

Promoted to ticket #861 and assigned to brian

brian Sat 12 Dec 2009

Ticket resolved in 1.0.48

changeset

brian Sat 12 Dec 2009

Renamed from Compiler error: returning an object from Void method to compiler: fix Obj to Void coercion bug

Login or Signup to reply.