File tree Expand file tree Collapse file tree 7 files changed +45
-3
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 7 files changed +45
-3
lines changed Original file line number Diff line number Diff 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 used in inline methods require @publicInBinary " , tree.srcPos)
109+ tree
110110 }
111111 else
112112 val accessor = useAccessor(tree)
Original file line number Diff line number Diff 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)
Original file line number Diff line number Diff line change 1+ -- Error: tests/neg/i22498.scala:7:32 ----------------------------------------------------------------------------------
2+ 7 | inline def proxy: Foo = new Foo(0) // error
3+ | ^^^
4+ | Private constructors used in inline methods require @publicInBinary
Original file line number Diff line number Diff line change 1+ //> using options -experimental
2+
3+ import scala .annotation .publicInBinary
4+
5+ class Foo :
6+ private def this (x : Int ) = this ()
7+ inline def proxy : Foo = new Foo (0 ) // error
Original file line number Diff line number Diff line change 1+ public Foo()
2+ public Foo(int)
3+ public Foo(java.lang.String)
Original file line number Diff line number Diff line change 1+ // scalajs: --skip
2+
3+ import scala .annotation .publicInBinary
4+ import scala .annotation .experimental
5+
6+ @ experimental
7+ class Foo :
8+ @ publicInBinary private def this (i : Int ) = this ()
9+ @ publicInBinary protected def this (i : String ) = this ()
10+
11+ @ experimental
12+ @ main def Test =
13+ println(classOf [Foo ].getConstructors().mkString(" \n " ))
Original file line number Diff line number Diff line change 1+ //> using options -experimental
2+
3+ import scala .annotation .publicInBinary
4+
5+ class Foo :
6+ @ publicInBinary private def this (x : Int ) = this ()
7+ inline def proxy : Foo = new Foo (0 )
8+
9+ @ main def Test =
10+ val x = (new Foo ).proxy
You can’t perform that action at this time.
0 commit comments