Aladdin - Scala Bugtracking
[#312] project: compiler priority: low category: bug
submitter assigned to status date submitted
Michel Martin fixed 2004-03-22 16:36:21.0
subject Single types should not contain null
code
object O {
  val x = "a";
  val y: x.type = null;
}
what happened
No error.
what expected An error stating that null is not of type x.type, since x.type should "contain" only one value, namely x.
[back to overview]
Changes of this bug report
Matthias  edited on  2004-03-22 21:57:39.0
I don't think that this is a bug. If "x.type" is a reference type and "null" is of type "AllRef," which is a subtype of all reference types, then it must be possible to assign "null" to a variable of a type like "x.type". What is an alternative subtype relationship? And what would we do for the following definition:
var a: a.type = _;
What value should we assign to variable a?
Michel  edited on  2004-03-23 07:41:59.0

What we discussed during the meeting is that the only value of type x.type is x itself. x.type is therefore completely isolated in the hierarchy. Your example would indeed be tricky if it was accepted, but right now the compiler says:

test_single.scala:5: illegal cyclic reference involving variable y
  var y: y.type = _;
         ^
one error found

In the general case, the default value for something of type x.type should be x itself.

Since we discuss this, the current solution has a problem (which can be seen as another bug of the constant folder, or as a symptom of why allowing null here is a bad idea). The following program does not throw a NullPointerException although it should:

final class C { def f = 1 }
object O with Application {
  val x = new C;
  var y: x.type = null;
  val z = y.f;
  Console.println("z=" + z);
}
Matthias  edited on  2004-03-23 08:37:06.0
Here's the full code:
object A {
    var b: Any = _;
    var a: b.type = _;
}
To what value shall we initialize variable a? Obviously not to null, because according to what you seem to have discussed in the meeting, this is not of type b.type.

I could now go on and introduce recursive dependencies where the Java runtime will automatically initialize such variables to null, no matter what you put in manually. This alone should show that taking identity/self types out of the type hierarchy is a bad idea.

Finally, I would like to point out difficulties with type inference. I have the impression that taking identity/self types out of the regular type hierarchy will result in an undecidable type inference mechanism.

There's also an issue with the usability of such types. Is x.type a subtype of Any? I guess it should, because otherwise we deconstruct what C# calls a unified type system.

Michel  edited on  2004-03-23 10:21:30.0

So, I have to say that the simple fact that you are allowed to write x.type when x is a variable confuses me quite a lot, as you can write this:

abstract class C { def f: Int };
class C1 extends C { def f = 1; }
class C2 extends C { def f = 2; }

object O with Application {
  var c1: C = new C1;
  var c2: c1.type = c1;
  c1 = new C2;
  Console.println("c1.f=" + c1.f + "  c2.f=" + c2.f);
}
Here, c2 is supposed to have type c1.type but in fact after the assignment, c1 and c2 are not even the same value...

Another thing which I find confusing when thinking a bit about them are default values. What is the default value of a variable of type scala.All? As far as I know, we don't have a single value of this type in Scala. The same goes for scala.AnyVal.

All in all, I'm pretty confused and I would like to take all this to the next meeting, if you don't mind, the bug tracking is not the best place for discussion. You have some convincing arguments that the change proposed here is not right, but on the other hand, there are some examples with the current solution that I think show problems with it.

Martin  edited on  2004-04-08 20:00:23.0
I changed the spec to demand that the prefix of a singelton type is a path (i.e. stable) of a type conforming to AnyRef: The type now includes null as a value:

A singleton type is of the form \lstinline@$p$.type@, where $p$ is a path pointing to a value expected to conform to \lstinline@scala.AnyRef@. The type denotes the set of values consisting of the value denoted by $p$ and \lstinline@null@.

I changed the compiler to conform to the new spec.