When is 0 actually null?

173 views
Skip to first unread message

Paul Butcher

unread,
May 20, 2012, 4:49:11 PM5/20/12
to scala-i...@googlegroups.com
I just stumbled across this:

scala> class Foo[T] { var x: T = _ }
defined class Foo

scala> val x = (new Foo[Int]).x
x: Int = 0

scala> val x: Any = (new Foo[Int]).x
x: Any = null

and along similar lines:

scala> def foo[T] = null.asInstanceOf[T]
foo: [T]=> T

scala> val x = foo[Int]
x: Int = 0

scala> val x: Any = foo[Int]
x: Any = null

This isn't just an academic issue. I'm currently working on ScalaMock 3, and I want to create mocks that return a sensible default value if none is specified. Right now, it's causing problems as described in the following thread:


--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Phillips

unread,
May 20, 2012, 5:10:08 PM5/20/12
to scala-i...@googlegroups.com


On Sun, May 20, 2012 at 1:49 PM, Paul Butcher <pa...@paulbutcher.com> wrote:
scala> val x: Any = (new Foo[Int]).x
x: Any = null
It gets better:

scala> class Foo[@specialized T] { var x: T = _ }
defined class Foo

scala> val x: Any = (new Foo[Int]).x
x: Any = 0


Notwithstanding the list of open tickets, there's no obvious improvement on the situation available.

Paul Butcher

unread,
May 20, 2012, 5:38:26 PM5/20/12
to scala-i...@googlegroups.com
Nice. I had no idea I'd stumbled across such a can of worms.

Your examples inspired me to experiment, which was clearly a foolish thing to do:

Welcome to Scala version 2.10.0-M3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def foo[@specialized T] = null.asInstanceOf[T]
foo: [T]=> T

scala> val x: Any = foo[Int]
exception when typing $line3.$read.$iw.$iw.foo()()
Object does not take parameters in file <console>
scala.reflect.internal.Types$TypeError: Object does not take parameters
at scala.tools.nsc.typechecker.Contexts$Context.issue(Contexts.scala:363)
at scala.tools.nsc.typechecker.Infer$Inferencer.issue(Infer.scala:218)
at scala.tools.nsc.typechecker.Typers$Typer.duplErrorTree$1(Typers.scala:2721)
at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:3067)
at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:4110)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4842)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.transformedOrTyped(Typers.scala:5220)
at scala.tools.nsc.typechecker.Typers$Typer.typedValDef(Typers.scala:1776)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4660)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4650)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5073)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun$transform$2.apply(Erasure.scala:1146)
at scala.tools.nsc.transform.Erasure$ErasureTransformer.transform(Erasure.scala:1142)
at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:228)
at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:432)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:398)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:392)
at scala.collection.Iterator$class.foreach(Iterator.scala:697)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1124)
at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:392)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1336)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1309)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1303)
at scala.tools.nsc.interpreter.IMain.compileSourcesKeepingRun(IMain.scala:461)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compileAndSaveRun(IMain.scala:845)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compile(IMain.scala:803)
at scala.tools.nsc.interpreter.IMain$Request.compile(IMain.scala:979)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:629)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:595)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:826)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:883)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:783)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:647)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:654)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:657)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:962)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:924)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:924)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:157)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:924)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:991)
at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:57)
at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:48)
at sbt.Console.console0$1(Console.scala:23)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
ReplGlobal.abort: unrecoverable error
error: unrecoverable error
exception when typing private[this] val x: Object = $line3.$read.$iw.$iw.foo()()
exception when typing object $iw extends Object {
  def <init>(): ... = {
    $iw.super.<init>();
    ()
  };
  private[this] val x: Object = $line3.$read.$iw.$iw.foo()();
  <stable> <accessor> def x(): Object = $iw.this.x
}
exception when typing object $iw extends Object {
  def <init>(): ... = {
    $iw.super.<init>();
    ()
  };
  object $iw extends Object {
    def <init>(): ... = {
      $iw.super.<init>();
      ()
    };
    private[this] val x: Object = $line3.$read.$iw.$iw.foo()();
    <stable> <accessor> def x(): Object = $iw.this.x
  }
}
exception when typing object $read extends Object {
  def <init>(): ... = {
    $read.super.<init>();
    ()
  };
  object $iw extends Object {
    def <init>(): ... = {
      $iw.super.<init>();
      ()
    };
    object $iw extends Object {
      def <init>(): ... = {
        $iw.super.<init>();
        ()
      };
      private[this] val x: Object = $line3.$read.$iw.$iw.foo()();
      <stable> <accessor> def x(): Object = $iw.this.x
    }
  }
}
exception when typing package $line4 {
  object $read extends Object {
    def <init>(): ... = {
      $read.super.<init>();
      ()
    };
    object $iw extends Object {
      def <init>(): ... = {
        $iw.super.<init>();
        ()
      };
      object $iw extends Object {
        def <init>(): ... = {
          $iw.super.<init>();
          ()
        };
        private[this] val x: Object = $line3.$read.$iw.$iw.foo()();
        <stable> <accessor> def x(): Object = $iw.this.x
      }
    }
  }
}

     while compiling:  <console>
       current phase:  erasure
     library version:  version 2.10.0-M3
    compiler version:  version 2.10.0-M3
  reconstructed args:  -deprecation -bootclasspath /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsfd.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/Resources/Java/JavaRuntimeSupport.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/ui.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/laf.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/sunrsasign.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsse.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jce.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/charsets.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-library.jar -feature -classpath /Users/paul/scala/ScalaMock3/target/scala-2.10.0-M3/classes:/Users/paul/.ivy2/cache/com.typesafe/config/jars/config-0.4.0.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-compiler.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jline.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jansi.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/config.jar -unchecked -Yrepl-sync

unhandled exception while transforming <console>
error: 
     while compiling:  <console>
       current phase:  erasure
     library version:  version 2.10.0-M3
    compiler version:  version 2.10.0-M3
  reconstructed args:  -deprecation -bootclasspath /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsfd.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/Resources/Java/JavaRuntimeSupport.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/ui.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/laf.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/sunrsasign.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsse.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jce.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/charsets.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-library.jar -feature -classpath /Users/paul/scala/ScalaMock3/target/scala-2.10.0-M3/classes:/Users/paul/.ivy2/cache/com.typesafe/config/jars/config-0.4.0.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-compiler.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jline.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jansi.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/config.jar -unchecked -Yrepl-sync

uncaught exception during compilation: scala.reflect.internal.FatalError
scala.reflect.internal.FatalError: 
     while compiling:  <console>
       current phase:  posterasure
     library version:  version 2.10.0-M3
    compiler version:  version 2.10.0-M3
  reconstructed args:  -deprecation -bootclasspath /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsfd.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar:/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/Resources/Java/JavaRuntimeSupport.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/ui.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/laf.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/sunrsasign.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jsse.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/jce.jar:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/charsets.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-library.jar -feature -classpath /Users/paul/scala/ScalaMock3/target/scala-2.10.0-M3/classes:/Users/paul/.ivy2/cache/com.typesafe/config/jars/config-0.4.0.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/scala-compiler.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jline.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/jansi.jar:/Users/paul/.sbt/0.11.2/boot/scala-2.10.0-M3/lib/config.jar -unchecked -Yrepl-sync

unrecoverable error
at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:45)
at scala.tools.nsc.Global.abort(Global.scala:202)
at scala.tools.nsc.interpreter.IMain$$anon$1.scala$tools$nsc$interpreter$ReplGlobal$$super$abort(IMain.scala:288)
at scala.tools.nsc.interpreter.ReplGlobal$class.abort(ReplGlobal.scala:21)
at scala.tools.nsc.interpreter.IMain$$anon$1.abort(IMain.scala:288)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:758)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.transformedOrTyped(Typers.scala:5220)
at scala.tools.nsc.typechecker.Typers$Typer.typedValDef(Typers.scala:1776)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4660)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1710)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$43.apply(Typers.scala:1579)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1578)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4654)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2540)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64$$anonfun$65.apply(Typers.scala:2636)
at scala.collection.immutable.List.loop$1(List.scala:163)
at scala.collection.immutable.List.mapConserve(List.scala:179)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$64.apply(Typers.scala:2636)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2635)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4650)
at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:751)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5015)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5073)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun$transform$2.apply(Erasure.scala:1146)
at scala.tools.nsc.transform.Erasure$ErasureTransformer.transform(Erasure.scala:1142)
at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:228)
at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:432)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:398)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:392)
at scala.collection.Iterator$class.foreach(Iterator.scala:697)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1124)
at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:392)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1336)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1309)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1303)
at scala.tools.nsc.interpreter.IMain.compileSourcesKeepingRun(IMain.scala:461)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compileAndSaveRun(IMain.scala:845)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compile(IMain.scala:803)
at scala.tools.nsc.interpreter.IMain$Request.compile(IMain.scala:979)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:629)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:595)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:826)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:883)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:783)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:647)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:654)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:657)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:962)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:924)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:924)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:157)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:924)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:991)
at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:57)
at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:48)
at sbt.Console.console0$1(Console.scala:23)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)

That entry seems to have slain the compiler.  Shall I replay
your session? I can re-run each line except the last one.
[y/n]

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

√iktor Ҡlang

unread,
May 20, 2012, 5:48:21 PM5/20/12
to scala-i...@googlegroups.com
What that in the "Things that go boom" category for 1000 points?
--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Paul Butcher

unread,
May 21, 2012, 6:54:31 AM5/21/12
to scala-i...@googlegroups.com
Does anyone have any suggestions for practical solutions to this for my particular use case?

I have a polymorphic class that needs to create default values for one of its type parameters. I thought that I could solve it with a Macro:

object DefaultValue {

  import language.experimental.macros

  

  def forType[T] = macro DefaultValueImpl.forType[T]

}


object DefaultValueImpl {

  

  def forType[T: c.TypeTag](c: Context): c.Expr[T] = c.tag[T] match {

    case c.mirror.ConcreteTypeTag.Byte => c.reify(0.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Short => c.reify(0.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Char => c.reify(0.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Int => c.reify(0.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Long => c.reify(0l.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Float => c.reify(0.0f.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Double => c.reify(0.0.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Boolean => c.reify(false.asInstanceOf[T])

    case c.mirror.ConcreteTypeTag.Unit => c.reify(().asInstanceOf[T])

    case _ => c.reify(null.asInstanceOf[T])

  }

}


Which works fine for concrete types:

scala> val x: Any = DefaultValue.forType[Int]
x: Any = 0

But not when given a type parameter:

scala> def foo[T] = { DefaultValue.forType[T] }
<console>:10: error: exception during macro expansion: 
java.lang.Error: T (AbstractTypeRef) is not concrete and cannot be used to construct a concrete type tag
at scala.reflect.api.TypeTags$ConcreteTypeTag$class.$init$(TypeTags.scala:194)
at scala.reflect.api.TypeTags$ConcreteTypeTag$$anon$17.<init>(TypeTags.scala:242)
at scala.reflect.api.TypeTags$ConcreteTypeTag$.apply(TypeTags.scala:242)
at org.scalamock.DefaultValueImpl$.forType(DefaultValue.scala:43)

       def foo[T] = { DefaultValue.forType[T] }

There must be *some* way to achieve the desired behaviour?

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Stefan Zeiger

unread,
May 21, 2012, 11:50:09 AM5/21/12
to scala-i...@googlegroups.com
On 2012-05-21 12:54, Paul Butcher wrote:
Does anyone have any suggestions for practical solutions to this for my particular use case?

I have a polymorphic class that needs to create default values for one of its type parameters. I thought that I could solve it with a Macro:

scala> def getDefault[T](implicit m: ClassManifest[T]): T = new Array[T](1)(0)
getDefault: [T](implicit m: ClassManifest[T])T

scala> getDefault[Int]
res0: Int = 0

scala> getDefault[String]
res1: String = null

If you want to create a value, you need to know the concrete type. I don't think macros can really do much for you in this case. OTOH if your "default value" only needs to satisfy the constraint that it can be assigned to a variable of the given type, just use null. If the variable is polymorphic (and not specialized), it's always an Object behind the scenes.

-sz

iulian dragos

unread,
May 21, 2012, 11:56:45 AM5/21/12
to scala-i...@googlegroups.com
On Mon, May 21, 2012 at 12:54 PM, Paul Butcher <pa...@paulbutcher.com> wrote:
> Does anyone have any suggestions for practical solutions to this for my
> particular use case?
>
> I have a polymorphic class that needs to create default values for one of
> its type parameters.

class WithDefault[T] {
var defaultVal: T = _

def getDefault: T = defaultVal
}

Would this help you?
--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais

Kevin Wright

unread,
May 21, 2012, 12:03:41 PM5/21/12
to scala-i...@googlegroups.com
Type Classes all the way! No new mechanisms required :)

Paul Butcher

unread,
May 21, 2012, 1:08:11 PM5/21/12
to scala-i...@googlegroups.com
Kevin, Iulian,

Many thanks for the suggestions, but unfortunately they don't work for my use case :-(

For example, with Iulian's approach:

scala> class WithDefault[T] {
     | var defaultVal: T = _
     | 
     | def getDefault: T = defaultVal
     | }
defined class WithDefault

scala> val x: Any = (new WithDefault[Int]).getDefault
x: Any = null

(note that x is null, not zero).

Stefan's is encouraging though - I just need to work out if I can plumb Manifest's through my code to the point where the default value is going to be created:

scala> def getDefault[T](implicit m: ClassManifest[T]): T = new Array[T](1)(0)
getDefault: [T](implicit m: ClassManifest[T])T

scala> val x: Any = getDefault[Int]
x: Any = 0

Thanks!

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Butcher

unread,
May 21, 2012, 1:26:09 PM5/21/12
to scala-i...@googlegroups.com
Apologies Kevin - I think that yours will work too, I just need to plumb the Constructible implicits all the way through.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Reply all
Reply to author
Forward
0 new messages