File tree 7 files changed +45
-3
lines changed
compiler/src/dotty/tools/dotc
7 files changed +45
-3
lines changed Original file line number Diff line number Diff line change @@ -105,8 +105,8 @@ object PrepareInlineable {
105
105
def preTransform (tree : Tree )(using Context ): Tree = tree match {
106
106
case tree : RefTree if needsAccessor(tree.symbol) =>
107
107
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
110
110
}
111
111
else
112
112
val accessor = useAccessor(tree)
Original file line number Diff line number Diff line change @@ -20,11 +20,14 @@ import ValueClasses.*
20
20
* Make private accessor in value class not-private. This is necessary to unbox
21
21
* the value class when accessing it from separate compilation units
22
22
*
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
24
24
* public or protected parameter accessor with the same name as the forwarder.
25
25
* This is necessary since private methods are not allowed to have the same name
26
26
* as inherited public ones.
27
27
*
28
+ * Also, make non-private any private constructor that is annotated with `@publicInBinary`.
29
+ * (See SIP-52)
30
+ *
28
31
* See discussion in https://github.com/scala/scala3/pull/784
29
32
* and https://github.com/scala/scala3/issues/783
30
33
*/
@@ -102,6 +105,8 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase
102
105
override def transformDefDef (tree : DefDef )(using Context ): DefDef = {
103
106
val sym = tree.symbol
104
107
tree.rhs match {
108
+ case _ if sym.isConstructor && sym.hasPublicInBinary =>
109
+ sym.ensureNotPrivate.installAfter(thisPhase)
105
110
case Apply (sel @ Select (_ : Super , _), _)
106
111
if sym.isAllOf(PrivateParamAccessor ) && sel.symbol.is(ParamAccessor ) && sym.name == sel.symbol.name =>
107
112
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