Should a `def` with a singleton type be considered stable?

vals make stable identifiers:

class Graph {
  class Node {
    val graph = Graph.this // val (without singleton type)
  }
  def useNode(node: Node) = ???
}

def useNode(node: Graph#Node) = node.graph.useNode(node)
// [...] Required: node.graph.Node

defs with singleton types do not (even though they will always return the same value):

class Graph {
  class Node {
    def graph: Graph.this.type = Graph.this // def with singleton type
  }
  def useNode(node: Node) = ???
}

def useNode(node: Graph#Node) = node.graph.useNode(node)
// [...] Required: [unknown type].Node

[/quote]

The question is then:
Could we make it so both introduce stable identifiers ?

It seems to me like this would be as sound as a before, is there a tricky edge-case ?

I don’t know the implications of “being stable” by heart, but it’s not true that it will always return the same value. The reason for that is that, for most types, null is a valid value (although I imagine that the fact that exceptions can be thrown is also an issue).

For example, the following code is valid:

import scala.util.Random

val x: String = "foo"
def y: x.type = if (Random.nextBoolean()) x else null

println(y)
println(y)
println(y)
println(y)
4 Likes

Oh wow, I would definitely not have expected that !

On the other hand, that same principle also applies to vals, and yet…

val x: "foo" = "foo"
def y: x.type = null
val z: x.type = null

println(y)
println(z)
2 Likes

Oh wow, I would definitely not … wait, I’m repeating myself

2 Likes

The obvious question here is: why do we need this? Why not just use a (lazy) val?

Not gonna lie, changing that example to have val x: "foo" = null and having it work is pretty bonkers: Scastie - An interactive playground for Scala.

Although later versions of the compiler seem to trigger an error.

A (lazy) val adds to the memory footprint of the class, whereas a def does not
(An inline val may solve the issue sometimes, but not always)

It also feels like it should work, which is usually an indication it should

if you use transparent inline then the compiler will do what you ask here