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
}
In this article