While investigating issue DAFFODIL-2146, I discovered that dstate.currentValue 
was taking on the value of "One(0)".


My first instinct is to attribute the to a bug in my enumeration support code 
(which it probably is), however my second instinct is to note that 
dstate.currentValue is declared to be of type AnyRef, while One(0) is of type 
Maybe, so the above situation should not be possible.


I was able to reproduce the issue in a small test program (using Daffodil as a 
dependency):


    val x1: Maybe[JLong] = One(JLong.valueOf(0))
    val x : Any = x1
    val y: AnyRef = Numbers.asAnyRef(x)
    println(x1.isInstanceOf[AnyRef])
    println(x.isInstanceOf[AnyRef])
    println(y)


I would expect the above program to output (not sure what I expect on the third 
line):


false

false

????


However, it actually outputs:


true
true
One(0)


Helpfully, Eclipse provides a warning on the first println that the expression 
can never be true.


For reference, Numbers.asAnyRef is defined as:


  def asAnyRef(n: Any): AnyRef = {
    n match {
      // case bi: BigInt => bi.bigInteger
      // case bd: BigDecimal => bd.bigDecimal
      case ar: AnyRef =>  ar
      case b: Boolean => JBoolean.valueOf(b)
      case _ => asNumber(n)
    }
  }


and I observe the same behaviour if I replace that call with a local version of 
the function:


  def asAnyRef(n: Any): AnyRef = {
    n match {
      case ar: AnyRef => ar
    }
  }



What appears to be happening is that Maybe is being recognized as an AnyRef by 
the pattern match, thereby allowing for a Maybe -> AnyRef cast which should not 
be possible.


Based on this, I tested the behavour of Numbers.asAnyRef on scala.Int value and 
found (by println debugging) that such a case is also going the the ar:AnyRef 
code path.


I suspect that the asAnyRef function is always a no-op at runtime, and the only 
reason our works normally is that scala will automagically cast between boxed 
and unboxed versions of the built-in anyVal types.


Assuming my analysis is correct, asAnyRef is really unsafeCoerceToAnyRef. As 
such, I would suggest that we remove the function and explicitly box values 
where Scala fails to do so automatically.


Thoughts?


Brandon T. Sloane

Associate, Services

[email protected] | tresys.com

Reply via email to