E195: Phantom Symbol Not Value
This error occurs when you try to use a compiler-generated phantom symbol as a standalone value. Phantom symbols are synthetic entries created by the compiler for various features but cannot be used as actual values.
This error is triggered for:
- Constructor proxies: Symbols representing factory methods for non-case classes (since 3.3.1)
- Context bound companions: Symbols representing witnesses for context bounds (since 3.5.0)
- Dummy capture parameters: Symbols representing references to capture parameters in experimental capture checking (since 3.7.2)
Note: This error code is used by multiple message classes and the exact message varies depending on the context.
Example
The following example demonstrates a dummy capture parameter being incorrectly used as a value. This occurs when using the experimental capture checking feature:
import language.experimental.captureChecking
class A:
type C^
def example(a: A): a.C = a.C
Here, C^ declares a capture parameter type, and the compiler creates a synthetic term C to allow referring to it in capture sets. However, this term cannot be used as an actual value.
Error
-- [E195] Type Error: example.scala:6:27 ---------------------------------------
6 |def example(a: A): a.C = a.C
| ^^^
| dummy term capture parameter value C cannot be used as a value
|-----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| A term capture parameter is a symbol made up by the compiler to represent a reference
| to a real capture parameter in capture sets. For instance, in
|
| class A:
| type C^
|
| there is just a type `A` declared but not a value `A`. Nevertheless, one can write
| the selection `(a: A).C` and use a a value, which works because the compiler created a
| term capture parameter for `C`. However, these term capture parameters are not real values,
| they can only be referred in capture sets.
-----------------------------------------------------------------------------
Solution
Use a real declared member instead of the phantom symbol:
import language.experimental.captureChecking
class A:
type C^
val getC: C = ???
def example(a: A): a.C = a.getC