E201: Non-Named Argument in Java Annotation

E201: Non-Named Argument in Java Annotation

이 에러는 Java로 정의된 애노테이션에 위치(이름 없는) 인자를 사용할 때 발생해요. Scala 3.6.0부터 모든 Java 애노테이션에는 이름 있는 인자(named argument)가 필수예요.

출처: Scala 3 Reference

본문

Java 애노테이션은 Scala에서 정확한 생성자 표현을 갖지 않아요. 그래서 예전 컴파일러는 위치 인자를 맞추기 위해 애노테이션 필드의 순서에 의존했어요. 이 방식은 취약한데, Java에서 애노테이션 필드의 순서를 바꾸는 것은 바이너리 호환은 되지만 위치 인자의 의미를 조용히 바꿀 수 있기 때문이에요.

예시 (Example)

class Foo:
  @Deprecated("reason")
  def oldMethod(): Unit = ()

에러 (Error)

-- [E201] Syntax Error: example.scala:2:14 -------------------------------------
2 |  @Deprecated("reason")
  |              ^^^^^^^^
  | Named arguments are required for Java defined annotations
  | This can be rewritten automatically under -rewrite -source 3.6-migration.
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | Starting from Scala 3.6.0, named arguments are required for Java defined annotations.
  | Java defined annotations don't have an exact constructor representation
  | and we previously relied on the order of the fields to create one.
  | One possible issue with this representation is the reordering of the fields.
  | Lets take the following example:
  |
  |   public @interface Annotation {
  |     int a() default 41;
  |     int b() default 42;
  |   }
  |
  | Reordering the fields is binary-compatible but it might affect the meaning of @Annotation(1)
  |
   -----------------------------------------------------------------------------

해결 방법 (Solution)

Java 애노테이션을 적용할 때 이름 있는 인자를 사용해요.

class Foo:
  @Deprecated(since = "reason")
  def oldMethod(): Unit = ()

대안으로, -rewrite -source 3.6-migration을 붙여 컴파일하면 위치 인자를 이름 있는 인자로 자동 변환해 주는 자동 재작성 기능을 이용할 수 있어요.