Skip to content

Commit 9865ef6

Browse files
authored
Merge pull request #15068 from griggt/disallow-targetname-on-toplevel-classes
Disallow `@targetName` on top-level `class`, `trait`, and `object`
2 parents 244317f + 47189c7 commit 9865ef6

File tree

32 files changed

+98
-44
lines changed

32 files changed

+98
-44
lines changed

compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID]:
176176
MatchableWarningID,
177177
CannotExtendFunctionID,
178178
LossyWideningConstantConversionID,
179-
ImplicitSearchTooLargeID
179+
ImplicitSearchTooLargeID,
180+
TargetNameOnTopLevelClassID
180181

181182
def errorNumber = ordinal - 2
182183

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,3 +2540,24 @@ import transform.SymUtils._
25402540
|
25412541
|${openSearchPairs.reverse.map(showQuery)}%\n%
25422542
"""
2543+
2544+
class TargetNameOnTopLevelClass(symbol: Symbol)(using Context)
2545+
extends SyntaxMsg(TargetNameOnTopLevelClassID):
2546+
def msg = em"${hl("@targetName")} annotation not allowed on top-level $symbol"
2547+
def explain =
2548+
val annot = symbol.getAnnotation(defn.TargetNameAnnot).get
2549+
em"""The @targetName annotation may be applied to a top-level ${hl("val")} or ${hl("def")}, but not
2550+
|a top-level ${hl("class")}, ${hl("trait")}, or ${hl("object")}.
2551+
|
2552+
|This restriction is due to the naming convention of Java classfiles, whose filenames
2553+
|are based on the name of the class defined within. If @targetName were permitted
2554+
|here, the name of the classfile would be based on the target name, and the compiler
2555+
|could not associate that classfile with the Scala-visible defined name of the class.
2556+
|
2557+
|If your use case requires @targetName, consider wrapping $symbol in an ${hl("object")}
2558+
|(and possibly exporting it), as in the following example:
2559+
|
2560+
|${hl("object Wrapper:")}
2561+
| $annot $symbol { ... }
2562+
|
2563+
|${hl("export")} Wrapper.${symbol.name} ${hl("// optional")}"""

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ object Checking {
505505
fail(TailrecNotApplicable(sym))
506506
else if sym.is(Inline) then
507507
fail("Inline methods cannot be @tailrec")
508+
if sym.hasAnnotation(defn.TargetNameAnnot) && sym.isClass && sym.isTopLevelClass then
509+
fail(TargetNameOnTopLevelClass(sym))
508510
if (sym.hasAnnotation(defn.NativeAnnot)) {
509511
if (!sym.is(Deferred))
510512
fail(NativeMembersMayNotHaveImplementation(sym))

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class CompilationTests {
171171
defaultOptions),
172172
compileFile("tests/neg-custom-args/i6300.scala", allowDeepSubtypes),
173173
compileFile("tests/neg-custom-args/infix.scala", defaultOptions.and("-source", "future", "-deprecation", "-Xfatal-warnings")),
174-
compileFile("tests/neg-custom-args/missing-alpha.scala", defaultOptions.and("-Yrequire-targetName", "-Xfatal-warnings")),
174+
compileFile("tests/neg-custom-args/missing-targetName.scala", defaultOptions.and("-Yrequire-targetName", "-Xfatal-warnings")),
175175
compileFile("tests/neg-custom-args/wildcards.scala", defaultOptions.and("-source", "future", "-deprecation", "-Xfatal-warnings")),
176176
compileFile("tests/neg-custom-args/indentRight.scala", defaultOptions.and("-no-indent", "-Xfatal-warnings")),
177177
compileDir("tests/neg-custom-args/adhoc-extension", defaultOptions.and("-source", "future", "-feature", "-Xfatal-warnings")),

docs/_docs/reference/other-new-features/targetName.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.h
2929
of type `String`. That string is called the _external name_ of the definition
3030
that's annotated.
3131

32-
2. A `@targetName` annotation can be given for all kinds of definitions.
32+
2. A `@targetName` annotation can be given for all kinds of definitions except a top-level `class`, `trait`, or `object`.
3333

3434
3. The name given in a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation must be a legal name
3535
for the defined entities on the host platform.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)