Skip to content

Inconsistent instantiation behavior #1088

@scabug

Description

@scabug

Given:

scala> class Foo { trait Qux { val x = 42 } }
defined class Foo

scala> class Bar(arg : Int) { trait Qux { val x = arg } }
defined class Bar

scala> val x : Foo = null
x: Foo = null

scala> val y : Bar = null
y: Bar = null

the following succeeds:

scala> val b = new x.type#Qux { };
b: java.lang.Object with x.Qux = $$anon$$1@137e216

but the following fails:

scala> val b = new y.type#Qux { };
java.lang.NullPointerException
        at Bar$$Qux$$class.$$init$$(<console>:4)
        at $$anon$$1.<init>(<console>:6)
        at .<init>(<console>:6)
        at .<clinit>(<console>)
        at RequestResult$$.<init>(<console>:3)
        at RequestResult$$.<clinit>(<console>)
        at RequestResult$$result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMeth...

Scala should be consistent in its operational behavior and both should fail with a NPE. Otherwise, evolving classes can have unforeseen impacts elsewhere in your code. The problem is not limited to using null, either:

scala> object Wrapper {
     |   lazy val x : Foo = x
     |   lazy val y : Bar = y
     | }
defined module Wrapper

scala> val b = new Wrapper.x.type#Qux { }
b: java.lang.Object with Wrapper.x.Qux = $$anon$$1@671416

scala> val b = new Wrapper.y.type#Qux { }
java.lang.StackOverflowError
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrapper$$.y(<console>:10)
        at Wrappe...

The problem is also not limited to merely to adding constructor arguments:

scala> trait Foo { trait Qux { val x = 42 } }
defined trait Foo

scala> trait Bar { val arg : Int; trait Qux { val x = arg } }
defined trait Bar

scala> val x : Foo = null
x: Foo = null

scala> val y : Bar = null
y: Bar = null

scala> val b = new x.type#Qux { };
b: java.lang.Object with x.Qux = $$anon$$1@14e54d8

scala> val b = new y.type#Qux { };
java.lang.NullPointerException
        at Bar$$Qux$$class.$$init$$(<console>:4)
        at $$anon$$1.<init>(<console>:6)
        at .<init>(<console>:6)
        at .<clinit>(<console>)
        at RequestResult$$.<init>(<console>:3)
        at RequestResult$$.<clinit>(<console>)
        at RequestResult$$result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMeth...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions