First, what @martijnhoekstra wrote is correct. Tho
@virus_dave: foo.type is a singleton type, as visible in its syntax, Types | Scala 2.12. The compound/refinement type is Foo { val x: Int }
, which is a supertype of foo.type. The spec is pretty specific on the syntax of those two:
A compound type T1 with
… with
Tn { R }
A singleton type is of the form p.p. type
Moreover, in this case, foo.type only contains foo and null, and is a strict subtype of Foo { val x: Int }, so you cannot confuse the two types even informally.
Now, asking about the type of foo is a somewhat ill-posed question, since multiple types are possible and since foo’s declaration and occurrences don’t have the same set of types, and some answers are more appropriate for one or the other.
For the declaration, the compiler will infer a type, most likely Foo { val x: Int }
as @martijnhoekstra says; to know, the only way is to parse scalac -Xprint:typer, as type inference is not specified. Inferring foo.type as the type of the declaration would not be very helpful.
Each expression is given a type by type inference, which depends on the expression and the expected type (following colored local type inference; you can google the paper).
So, the most specific type possible for occurrences of a val (any val) is its singleton type, but the immediate supertype is (typically) the declaration type.
Finally, the spec gives a first approximation of the expected compiler behavior, which is not necessarily easy to parse.
To check if an expression e can be given a type T, try adding e : T and compiling. However, adding a type ascription changes the expected type used to infer e’s type; to avoid that, you can instead write final val x = e; x:T. Using final affects type inference of x’s type.
And to check the subtype relation, summon witnesses of <:< via implicitly.