#949 IllegalAccess in mixin field override

msl Sun 31 Jan 2010

I'm trying to assemble a hierarchy that looks something like:

mixin BottomMI {
  abstract internal Obj[] objs
}

mixin MiddleMI : BottomMI {
  Obj addObj(Obj obj) {
    objs.add(obj)
    return obj
  }
}

abstract class MiddleCL : MiddleMI {
  override internal Obj[] objs := [,]
  abstract Void doSomething()
}

class TopCL : MiddleCL {
  override Void doSomething() {
    echo("Doing something")
  }
}

However, when I try to use these classes (built into a pod by the standard build::BuildPod class - not that this seems to matter as putting all of the code listed here into a single file and running it behaves much the same, as does fansh) using code such as:

using bugquestionmark
class Test {
  Void main() {
    tc := TopCL()
    tc.doSomething()
    tc.addObj("ASD")
  }
}

I get the following:

~/bugquestionmark$ fan Test.fan 
Doing something
sys::Err: java.lang.IllegalAccessError: fan.bugquestionmark.TopCL.objs()Lfan/sys/List;
  bugquestionmark::MiddleMI$.addObj (Unknown:3)
  bugquestionmark::MiddleCL.addObj (MiddleClass.fan)
  Test_0::Test.main (/Users/martin/bugquestionmark/Test.fan:6)
  java.lang.reflect.Method.invoke (Method.java:597)
  fan.sys.Method.invoke (Method.java:536)
  fan.sys.Method$MethodFunc.callOn (Method.java:214)
  fan.sys.Method.callOn (Method.java:148)
  fanx.tools.Fan.callMain (Fan.java:137)
  fanx.tools.Fan.executeFile (Fan.java:88)
  fanx.tools.Fan.execute (Fan.java:34)
  fanx.tools.Fan.run (Fan.java:241)
  fanx.tools.Fan.main (Fan.java:279)

The error is obviously around visibility of the declared Obj[] (internal) but my understanding of internal is that other classes within the same pod should be able to see but not outside of the pod - criteria which are met by this sample.

Thoughts?

Martin

brian Sun 31 Jan 2010

Promoted to ticket #949 and assigned to brian

Its definitely a bug somewhere in how the class is overriding the mixin field.

brian Sun 31 Jan 2010

Renamed from Bug or PEBKAC? to IllegalAccess in mixin field override

tactics Mon 8 Mar 2010

I narrowed down the problem a little more. It's an issue with making the objs slot internal. Remove the internal keyword from the slot and its override, and the code works normally.

mixin Collection 
{
  abstract internal Obj[] objs
  Obj add(Obj obj) 
  {
    objs.add(obj)
    return obj
  }
}

class ListCollection : Collection
{
  override internal Obj[] objs := [,]
}

class Main 
{
  Void main() 
  {
    list := ListCollection()
    list.add("ASD")
  }
}

brian Tue 23 Mar 2010

-

brian Tue 23 Mar 2010

Ticket resolved in 1.0.52

This issue is rather tricky.

In Java, the members of an interface must be public (they cannot be package private).

It also seems that if a class overrides an interface's public method using a package private method, then Java throws IllegalAccessError.

So effectively it is impossible to really map Fantom's internal modifier to Java's package private.

Instead I flipped so that Fantom internal slots always emit as Java public members.

tactics Tue 23 Mar 2010

Was the original intention to keep scope modifiers consistent with the hosting language?

brian Tue 23 Mar 2010

Was the original intention to keep scope modifiers consistent with the hosting language?

Well if possible to keep it close. Although in reality Fantom internal might be more like "module" scope in Java-7 assuming that happens.

Login or Signup to reply.