Skip to content

Commit 1b3cc3a

Browse files
committed
Require @publicInBinary on overrides
1 parent e5e3dcf commit 1b3cc3a

File tree

4 files changed

+11
-7
lines changed

4 files changed

+11
-7
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,10 +1033,7 @@ object SymDenotations {
10331033

10341034
/** Is this a member that will become public in the generated binary */
10351035
def hasPublicInBinary(using Context): Boolean =
1036-
isTerm && (
1037-
hasAnnotation(defn.PublicInBinaryAnnot) ||
1038-
allOverriddenSymbols.exists(sym => sym.hasAnnotation(defn.PublicInBinaryAnnot))
1039-
)
1036+
isTerm && hasAnnotation(defn.PublicInBinaryAnnot)
10401037

10411038
/** ()T and => T types should be treated as equivalent for this symbol.
10421039
* Note: For the moment, we treat Scala-2 compiled symbols as loose matching,

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,12 @@ object Checking {
544544
else if !sym.owner.isClass && !(sym.is(Param) && sym.owner.isConstructor) then fail(em"@publicInBinary cannot be used on local definitions")
545545
else if sym.is(ParamAccessor) && sym.is(Private) then fail(em"@publicInBinary cannot be non `val` constructor parameters")
546546
else if sym.is(Private) && !sym.privateWithin.exists && !sym.isConstructor then fail(em"@publicInBinary cannot be used on private definitions\n\nConsider using `private[${sym.owner.name}]` or `protected` instead")
547+
else
548+
sym.allOverriddenSymbols.find(sym => sym.hasAnnotation(defn.PublicInBinaryAnnot)) match
549+
case Some(overriddenSym) =>
550+
fail(em"""This definitions ${if sym.is(Override) then "overrides" else "implements"} @publicInBinary ${overriddenSym.showLocated}.
551+
|This definition must also be marked as @publicInBinary.""")
552+
case None => ()
547553
if (sym.hasAnnotation(defn.NativeAnnot)) {
548554
if (!sym.is(Deferred))
549555
fail(NativeMembersMayNotHaveImplementation(sym))

library/src/scala/annotation/publicInBinary.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package scala.annotation
22

3-
/** A binary API is a definition that is annotated with `@publicInBinary` or overrides a definition annotated with `@publicInBinary`.
3+
/** A binary API is a definition that is annotated with `@publicInBinary`.
44
* This annotation can be placed on `def`, `val`, `lazy val`, `var`, class constructors, `object`, and `given` definitions.
55
* A binary API will be publicly available in the bytecode. Tools like TASTy MiMa will take this into account to check
66
* compatibility.

tests/run/publicInBinary/Lib_1.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ class Foo(@publicInBinary private[Foo] val paramVal: Int, @publicInBinary privat
2121
paramVal + paramVar + protectedVal + packagePrivateVal + protectedVar + packagePrivateVar
2222

2323
class Bar() extends Foo(3, 3):
24+
@publicInBinary
2425
override protected val protectedVal: Int = 2
25-
26+
@publicInBinary
2627
override private[foo] val packagePrivateVal: Int = 2
2728

2829
inline def bar: Int = protectedVal + packagePrivateVal
2930

3031
class Baz() extends Foo(4, 4):
31-
@publicInBinary // TODO warn? Not needed because Foo.protectedVal is already @publicInBinary
32+
@publicInBinary
3233
override protected val protectedVal: Int = 2
3334

3435
@publicInBinary

0 commit comments

Comments
 (0)