E169: TargetName On Top-Level Class

This error occurs when the @targetName annotation is applied to a top-level class, trait, or object.

The @targetName annotation is used to specify an alternative name for a definition in the generated bytecode, primarily for interoperability purposes. However, it cannot be applied to top-level type definitions because the class name in the bytecode must match the filename and package structure.


Example

import scala.annotation.targetName

@targetName("Foo") class MyClass

Error

-- [E169] Syntax Error: example.scala:3:25 -------------------------------------
3 |@targetName("Foo") class MyClass
  |                         ^
  |             @targetName annotation not allowed on top-level class MyClass
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | The @targetName annotation may be applied to a top-level val or def, but not
  | a top-level class, trait, or object.
  |
  | This restriction is due to the naming convention of Java classfiles, whose filenames
  | are based on the name of the class defined within. If @targetName were permitted
  | here, the name of the classfile would be based on the target name, and the compiler
  | could not associate that classfile with the Scala-visible defined name of the class.
  |
  | If your use case requires @targetName, consider wrapping class MyClass in an object
  | (and possibly exporting it), as in the following example:
  |
  | object Wrapper:
  |   @targetName("Foo") class MyClass { ... }
  |
  | export Wrapper.MyClass  // optional
   -----------------------------------------------------------------------------

Solution

import scala.annotation.targetName

// @targetName can be used on methods and vals
class MyClass {
  @targetName("addOne") def ++(x: Int): Int = x + 1
}
import scala.annotation.targetName

// Wrap in an object if you need targetName on a class
object Wrapper {
  @targetName("FooClass") class MyClass
}