E195: Phantom Symbol Not Value

E195: Phantom Symbol Not Value

이 에러는 컴파일러가 만들어 낸 팬텀(phantom) 심볼을 독립된 값으로 사용하려고 할 때 발생해요. 팬텀 심볼은 여러 기능을 위해 컴파일러가 합성해 만든 항목이지만, 실제 값으로는 쓸 수 없어요.

출처: Scala 3 Reference

본문

이 에러는 다음과 같은 경우에 발생해요.

  • Constructor proxies: 케이스 클래스가 아닌 클래스의 팩토리 메서드를 나타내는 심볼 (3.3.1부터)
  • Context bound companions: 컨텍스트 바운드의 증인(witness)을 나타내는 심볼 (3.5.0부터)
  • Dummy capture parameters: 실험적 캡처 체킹(capture checking)에서 캡처 파라미터에 대한 참조를 나타내는 심볼 (3.7.2부터)

참고: 이 에러 코드는 여러 메시지 클래스에서 사용되므로, 정확한 메시지는 문맥에 따라 달라져요.

예시 (Example)

아래 예시는 더미 캡처 파라미터를 값으로 잘못 사용한 경우를 보여줘요. 실험적 캡처 체킹 기능을 사용할 때 발생해요.

import language.experimental.captureChecking

class A:
  type C^

def example(a: A): a.C = a.C

여기서 C^는 캡처 파라미터 타입을 선언하고, 컴파일러는 캡처 집합에서 이를 참조할 수 있도록 합성 용어(term) C를 만들어요. 하지만 이 용어는 실제 값으로 사용될 수는 없어요.

에러 (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)

팬텀 심볼 대신 실제로 선언된 멤버를 사용해요.

import language.experimental.captureChecking

class A:
  type C^
  val getC: C = ???

def example(a: A): a.C = a.getC