Skip to content

Commit c3258eb

Browse files
committed
Test support of @binaryAPI on constructors
1 parent d4472ae commit c3258eb

File tree

8 files changed

+121
-3
lines changed

8 files changed

+121
-3
lines changed

compiler/src/dotty/tools/dotc/inlines/PrepareInlineable.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ object PrepareInlineable {
253253

254254
/** Create an inline accessor for this definition. */
255255
def makePrivateBinaryAPIAccessor(sym: Symbol)(using Context): Unit =
256-
if !sym.is(Accessor) then
256+
if !sym.is(Accessor) && sym.owner.isClass then
257257
val ref = tpd.ref(sym).asInstanceOf[RefTree]
258258
val accessor = InsertPrivateBinaryAPIAccessors.useAccessor(ref)
259259
if sym.is(Mutable) then

compiler/src/dotty/tools/dotc/transform/AccessProxies.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ abstract class AccessProxies {
7575
def needsAccessor(sym: Symbol)(using Context): Boolean
7676

7777
def ifNoHost(reference: RefTree)(using Context): Tree = {
78-
assert(false, "no host found for $reference with ${reference.symbol.showLocated} from ${ctx.owner}")
78+
assert(false, i"no host found for $reference with ${reference.symbol.showLocated} from ${ctx.owner}")
7979
reference
8080
}
8181

@@ -153,7 +153,7 @@ abstract class AccessProxies {
153153
def accessorIfNeeded(tree: Tree)(using Context): Tree = tree match {
154154
case tree: RefTree if needsAccessor(tree.symbol) =>
155155
if (tree.symbol.isConstructor) {
156-
report.error("Implementation restriction: cannot use private constructors in inlineable methods", tree.srcPos)
156+
report.error("Cannot use private constructors in inline methods. You can use @binaryAPI to make constructor accessible in inline methods.", tree.srcPos)
157157
tree // TODO: create a proper accessor for the private constructor
158158
}
159159
else useAccessor(tree)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ object Checking {
533533
else if sym.is(Private) then fail(em"@binaryAPI cannot be used on private definitions.\n\nCould the definition `private[${sym.owner.name}]` or `protected` instead or use `@binaryAPIAccessor` instead of `@binaryAPI`.")
534534
if sym.hasAnnotation(defn.BinaryAPIAccessorAnnot) then
535535
if sym.is(Enum) then fail(em"@binaryAPIAccessor cannot be used on enum definitions.")
536+
else if sym.isConstructor then fail(em"@binaryAPIAccessor cannot be used on constructors.")
536537
else if sym.isType && !sym.is(Module) && !(sym.is(Given) || sym.companionModule.is(Given)) then fail(em"@binaryAPIAccessor cannot be used on ${sym.showKind} definitions")
537538
else if !sym.owner.isClass && !(sym.is(Param) && sym.owner.isConstructor) then fail(em"@binaryAPIAccessor cannot be used on local definitions.")
538539
if (sym.hasAnnotation(defn.NativeAnnot)) {

tests/neg/binaryAPI.check

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,30 @@
2222
19 | @binaryAPI case B(a: Int) // error
2323
| ^
2424
| @binaryAPI cannot be used on enum definitions.
25+
-- Error: tests/neg/binaryAPI.scala:22:9 -------------------------------------------------------------------------------
26+
22 |class Foo @binaryAPI private (x: Int): // error
27+
| ^
28+
| @binaryAPI cannot be used on private definitions.
29+
|
30+
| Could the definition `private[Foo]` or `protected` instead or use `@binaryAPIAccessor` instead of `@binaryAPI`.
31+
-- Error: tests/neg/binaryAPI.scala:23:25 ------------------------------------------------------------------------------
32+
23 | @binaryAPI private def this(x: Int, y: Int) = this(x + y) // error
33+
| ^
34+
| @binaryAPI cannot be used on private definitions.
35+
|
36+
| Could the definition `private[Foo]` or `protected` instead or use `@binaryAPIAccessor` instead of `@binaryAPI`.
37+
-- Error: tests/neg/binaryAPI.scala:25:9 -------------------------------------------------------------------------------
38+
25 |class Bar @binaryAPI private[this] (x: Int): // error
39+
| ^
40+
| @binaryAPI cannot be used on private definitions.
41+
|
42+
| Could the definition `private[Bar]` or `protected` instead or use `@binaryAPIAccessor` instead of `@binaryAPI`.
43+
-- Error: tests/neg/binaryAPI.scala:26:31 ------------------------------------------------------------------------------
44+
26 | @binaryAPI private[this] def this(x: Int, y: Int) = this(x + y) // error
45+
| ^
46+
| @binaryAPI cannot be used on private definitions.
47+
|
48+
| Could the definition `private[Bar]` or `protected` instead or use `@binaryAPIAccessor` instead of `@binaryAPI`.
2549
-- Error: tests/neg/binaryAPI.scala:5:16 -------------------------------------------------------------------------------
2650
5 |@binaryAPI type A // error
2751
| ^

tests/neg/binaryAPI.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,10 @@ def f(@binaryAPI x: Int) = 3 // error
1717
enum Enum2:
1818
@binaryAPI case A // error
1919
@binaryAPI case B(a: Int) // error
20+
21+
22+
class Foo @binaryAPI private (x: Int): // error
23+
@binaryAPI private def this(x: Int, y: Int) = this(x + y) // error
24+
25+
class Bar @binaryAPI private[this] (x: Int): // error
26+
@binaryAPI private[this] def this(x: Int, y: Int) = this(x + y) // error

tests/neg/binaryAPIAccessor.check

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
-- Error: tests/neg/binaryAPIAccessor.scala:6:25 -----------------------------------------------------------------------
2+
6 |@binaryAPIAccessor class C: // error
3+
| ^
4+
| @binaryAPIAccessor cannot be used on class definitions
5+
-- Error: tests/neg/binaryAPIAccessor.scala:8:27 -----------------------------------------------------------------------
6+
8 | @binaryAPIAccessor def g = () // error
7+
| ^
8+
| @binaryAPIAccessor cannot be used on local definitions.
9+
-- Error: tests/neg/binaryAPIAccessor.scala:10:27 ----------------------------------------------------------------------
10+
10 |class D[@binaryAPIAccessor T] // error
11+
| ^
12+
| @binaryAPIAccessor cannot be used on type definitions
13+
-- Error: tests/neg/binaryAPIAccessor.scala:14:24 ----------------------------------------------------------------------
14+
14 |@binaryAPIAccessor enum Enum1: // error
15+
| ^
16+
| @binaryAPIAccessor cannot be used on enum definitions.
17+
-- Error: tests/neg/binaryAPIAccessor.scala:18:26 ----------------------------------------------------------------------
18+
18 | @binaryAPIAccessor case A // error
19+
| ^
20+
| @binaryAPIAccessor cannot be used on enum definitions.
21+
-- Error: tests/neg/binaryAPIAccessor.scala:19:26 ----------------------------------------------------------------------
22+
19 | @binaryAPIAccessor case B(a: Int) // error
23+
| ^
24+
| @binaryAPIAccessor cannot be used on enum definitions.
25+
-- Error: tests/neg/binaryAPIAccessor.scala:21:9 -----------------------------------------------------------------------
26+
21 |class Foo @binaryAPIAccessor private (x: Int): // error
27+
| ^
28+
| @binaryAPIAccessor cannot be used on constructors.
29+
-- Error: tests/neg/binaryAPIAccessor.scala:22:33 ----------------------------------------------------------------------
30+
22 | @binaryAPIAccessor private def this(x: Int, y: Int) = this(x + y) // error
31+
| ^
32+
| @binaryAPIAccessor cannot be used on constructors.
33+
-- Error: tests/neg/binaryAPIAccessor.scala:24:9 -----------------------------------------------------------------------
34+
24 |class Bar @binaryAPIAccessor private[this] (x: Int): // error
35+
| ^
36+
| @binaryAPIAccessor cannot be used on constructors.
37+
-- Error: tests/neg/binaryAPIAccessor.scala:25:39 ----------------------------------------------------------------------
38+
25 | @binaryAPIAccessor private[this] def this(x: Int, y: Int) = this(x + y) // error
39+
| ^
40+
| @binaryAPIAccessor cannot be used on constructors.
41+
-- Error: tests/neg/binaryAPIAccessor.scala:5:24 -----------------------------------------------------------------------
42+
5 |@binaryAPIAccessor type A // error
43+
| ^
44+
| @binaryAPIAccessor cannot be used on type definitions
45+
-- Error: tests/neg/binaryAPIAccessor.scala:12:25 ----------------------------------------------------------------------
46+
12 |def f(@binaryAPIAccessor x: Int) = 3 // error
47+
| ^
48+
| @binaryAPIAccessor cannot be used on local definitions.

tests/neg/binaryAPIAccessor.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package foo
2+
3+
import scala.annotation.binaryAPIAccessor
4+
5+
@binaryAPIAccessor type A // error
6+
@binaryAPIAccessor class C: // error
7+
def f: Unit =
8+
@binaryAPIAccessor def g = () // error
9+
()
10+
class D[@binaryAPIAccessor T] // error
11+
12+
def f(@binaryAPIAccessor x: Int) = 3 // error
13+
14+
@binaryAPIAccessor enum Enum1: // error
15+
case A
16+
17+
enum Enum2:
18+
@binaryAPIAccessor case A // error
19+
@binaryAPIAccessor case B(a: Int) // error
20+
21+
class Foo @binaryAPIAccessor private (x: Int): // error
22+
@binaryAPIAccessor private def this(x: Int, y: Int) = this(x + y) // error
23+
24+
class Bar @binaryAPIAccessor private[this] (x: Int): // error
25+
@binaryAPIAccessor private[this] def this(x: Int, y: Int) = this(x + y) // error

tests/pos/binaryAPI.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,16 @@ package traits {
123123
val baz = new Baz
124124
baz.foo
125125
}
126+
127+
package constructors {
128+
class Foo @binaryAPI private[constructors] (x: Int):
129+
@binaryAPI private[constructors] def this(x: Int, y: Int) = this(x + y)
130+
131+
inline def newFoo(x: Int) = new Foo(x)
132+
inline def newFoo(x: Int, y: Int) = new Foo(x, y)
133+
}
134+
135+
def testConstructors =
136+
import constructors.*
137+
val f = newFoo(1)
138+
val g = newFoo(1, 2)

0 commit comments

Comments
 (0)