class C {
object O
}
val x: C#O.type = (new C).O // error: ';' expected but '.' found
val y: C#(O.type) = (new C).O // error: identifier expected but '(' found
Is there a legal syntax for this type?
EDIT:
val x: c.O.type forSome { val c: C } = (new C).O
gives
ScalaFiddle.scala:4: error: type mismatch;
found : ScalaFiddle.this.C#O.type
required: c.type#O.type forSome { type c.type <: ScalaFiddle.this.C with scala.this.Singleton{} }
val x: c.O.type forSome { val c: C } = (new C).O
^
So Scala compiler understands this type and shows it as C#O.type
. It seems this case was just overlooked when creating the grammar.
Overview
{ val y = new C; y.O }
?I can't prove that it is impossible, but at least I wanted to make sure that I didn't give up without trying. It's not really an answer, rather a list of failed attempts, maybe someone finds it amusing, maybe someone finds the script (in the second part) for generating the list of error messages useful for reporting their findings...
A few attempts to write down the type
Systematic rewriting of AlexeyRomanov's attempt that looked most promising:
Some more or less unsystematic attempts with type-lambda like constructs:
Experiment with nested
forSome
:Experiments with additional type members in
C
:This actually compiles, but modifies the right hand side, so I guess it doesn't count:
Conclusion: Looks impossible to me.
Bash script that generates all the error messages
To generate all the error messages (without file paths and feature warnings), save the part of the post above this line as
saved_post.txt
, and then run the following script in the same directory:This generates the following wall of error messages (Hey, I've tried to clean it up!):
EDIT 2018-04-11:
Just stumbled upon this here in 6.4 of the specification:
The parts before this sentence describing the "not-other" expressions seem to refer to ordinary names and stable identifiers. Given this clause in the specification, it is not entirely clear to me why
(new C).O
is not typed in exactly the same way as{val y = new C; y.O}
, because after this rewriting, the problematic codewould look just like the only working proposal that I could come up with in the above series of attempts:
Could the inferred type
C#O.type
actually be a bug, andc.O.type forSome { val c: C }
be the type mandated by the specification? I wouldn't go so far claiming that it is a bug, I'm not familiar enough with the formulations used in the spec.The object
O
only exists with an instance ofC
, so its type will need to tied with an instance ofC
as well. Hence you can't doC#O.type
orC#(O.type)
, but you need to have an instance ofC
first, e.g.:EDIT: Alexey Romanov has commented below that my conclusion is incorrect, which can be demonstrated by this example below:
So I actually don't know why
B#A
works butC#O.type
doesn't work :(