Skip to content

Commit 6d84032

Browse files
committed
fix: publicInBinary has effect on secondary constructors
1 parent 4952e0a commit 6d84032

File tree

4 files changed

+22
-3
lines changed

4 files changed

+22
-3
lines changed

Diff for: compiler/src/dotty/tools/dotc/inlines/PrepareInlineable.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ object PrepareInlineable {
105105
def preTransform(tree: Tree)(using Context): Tree = tree match {
106106
case tree: RefTree if needsAccessor(tree.symbol) =>
107107
if (tree.symbol.isConstructor) {
108-
report.error("Implementation restriction: cannot use private constructors in inline methods", tree.srcPos)
109-
tree // TODO: create a proper accessor for the private constructor
108+
report.error("Private constructors in inline methods requires @publicInBinary", tree.srcPos)
109+
tree
110110
}
111111
else
112112
val accessor = useAccessor(tree)

Diff for: compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ import ValueClasses.*
2020
* Make private accessor in value class not-private. This is necessary to unbox
2121
* the value class when accessing it from separate compilation units
2222
*
23-
* Also, make non-private any private parameter forwarders that forward to an inherited
23+
* Make non-private any private parameter forwarders that forward to an inherited
2424
* public or protected parameter accessor with the same name as the forwarder.
2525
* This is necessary since private methods are not allowed to have the same name
2626
* as inherited public ones.
2727
*
28+
* Also, make non-private any private constructor that is annotated with `@publicInBinary`.
29+
* (See SIP-52)
30+
*
2831
* See discussion in https://github.com/scala/scala3/pull/784
2932
* and https://github.com/scala/scala3/issues/783
3033
*/
@@ -102,6 +105,8 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase
102105
override def transformDefDef(tree: DefDef)(using Context): DefDef = {
103106
val sym = tree.symbol
104107
tree.rhs match {
108+
case _ if sym.isConstructor && sym.hasPublicInBinary =>
109+
sym.ensureNotPrivate.installAfter(thisPhase)
105110
case Apply(sel @ Select(_: Super, _), _)
106111
if sym.isAllOf(PrivateParamAccessor) && sel.symbol.is(ParamAccessor) && sym.name == sel.symbol.name =>
107112
sym.ensureNotPrivate.installAfter(thisPhase)

Diff for: tests/run/i22497.check

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public Foo()
2+
public Foo(int)
3+
public Foo(java.lang.String)

Diff for: tests/run/i22497.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.annotation.publicInBinary
2+
import scala.annotation.experimental
3+
4+
@experimental
5+
class Foo:
6+
@publicInBinary private def this(i: Int) = this()
7+
@publicInBinary protected def this(i: String) = this()
8+
9+
@experimental
10+
@main def Test =
11+
println(classOf[Foo].getConstructors().mkString("\n"))

0 commit comments

Comments
 (0)