Skip to content

Commit 04ded7e

Browse files
committed
Split into @binaryAPI and @binaryAPIAccessor
* `@binaryAPI` makes the API public. Cannot be used on `private[this]`. * `@binaryAPIAccessor` generates the private accessor.
1 parent ab1a18f commit 04ded7e

29 files changed

+186
-107
lines changed

compiler/src/dotty/tools/backend/jvm/PostProcessorFrontendAccess.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import dotty.tools.dotc.core.Contexts.Context
99
import dotty.tools.dotc.report
1010
import dotty.tools.dotc.core.Phases
1111

12-
import scala.annotation.binaryAPI
12+
import scala.annotation.binaryAPIAccessor
1313

1414
/**
1515
* Functionality needed in the post-processor whose implementation depends on the compiler
@@ -22,7 +22,7 @@ sealed abstract class PostProcessorFrontendAccess {
2222
def backendReporting: BackendReporting
2323
def getEntryPoints: List[String]
2424

25-
@binaryAPI
25+
@binaryAPIAccessor
2626
private val frontendLock: AnyRef = new Object()
2727
inline final def frontendSynch[T](inline x: => T): T = frontendLock.synchronized(x)
2828
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import NameKinds.AvoidNameKind
1515
import util.SimpleIdentitySet
1616
import NullOpsDecorator.stripNull
1717

18-
import scala.annotation.binaryAPI
18+
import scala.annotation.{binaryAPI, binaryAPIAccessor}
1919

2020
/** Methods for adding constraints and solving them.
2121
*
@@ -112,7 +112,8 @@ trait ConstraintHandling {
112112
* of `1`. So the lower bound is `1 | x.M` and when we level-avoid that we
113113
* get `1 | Int & String`, which simplifies to `Int`.
114114
*/
115-
@binaryAPI private var myTrustBounds = true
115+
@binaryAPIAccessor
116+
private var myTrustBounds = true
116117

117118
inline def withUntrustedBounds(op: => Type): Type =
118119
val saved = myTrustBounds

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import classfile.ReusableDataReader
3030
import StdNames.nme
3131
import compiletime.uninitialized
3232

33-
import scala.annotation.binaryAPI
33+
import scala.annotation.{binaryAPI, binaryAPIAccessor}
3434
import scala.annotation.internal.sharable
3535

3636
import DenotTransformers.DenotTransformer
@@ -806,7 +806,7 @@ object Contexts {
806806
* Note: plain TypeComparers always take on the kind of the outer comparer if they are in the same context.
807807
* In other words: tracking or explaining is a sticky property in the same context.
808808
*/
809-
@binaryAPI
809+
@binaryAPIAccessor
810810
private def comparer(using Context): TypeComparer =
811811
util.Stats.record("comparing")
812812
val base = ctx.base

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ class Definitions {
10401040
@tu lazy val RetainsAnnot: ClassSymbol = requiredClass("scala.annotation.retains")
10411041
@tu lazy val RetainsByNameAnnot: ClassSymbol = requiredClass("scala.annotation.retainsByName")
10421042
@tu lazy val BinaryAPIAnnot: ClassSymbol = requiredClass("scala.annotation.binaryAPI")
1043+
@tu lazy val BinaryAPIAccessorAnnot: ClassSymbol = requiredClass("scala.annotation.binaryAPIAccessor")
10431044

10441045
@tu lazy val JavaRepeatableAnnot: ClassSymbol = requiredClass("java.lang.annotation.Repeatable")
10451046

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,9 +1042,13 @@ object SymDenotations {
10421042
def isBinaryAPI(using Context): Boolean =
10431043
isTerm && (
10441044
hasAnnotation(defn.BinaryAPIAnnot) ||
1045-
allOverriddenSymbols.exists(_.hasAnnotation(defn.BinaryAPIAnnot))
1045+
allOverriddenSymbols.exists(sym => sym.hasAnnotation(defn.BinaryAPIAnnot))
10461046
)
10471047

1048+
/** Is this a member that will have an accessor in the generated binary */
1049+
def isBinaryAPIAccessor(using Context): Boolean =
1050+
isTerm && hasAnnotation(defn.BinaryAPIAccessorAnnot)
1051+
10481052
/** ()T and => T types should be treated as equivalent for this symbol.
10491053
* Note: For the moment, we treat Scala-2 compiled symbols as loose matching,
10501054
* because the Scala library does not always follow the right conventions.

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import reporting.trace
2525
import annotation.constructorOnly
2626
import cc.{CapturingType, derivedCapturingType, CaptureSet, stripCapturing, isBoxedCapturing, boxed, boxedUnlessFun, boxedIfTypeParam, isAlwaysPure}
2727

28-
import scala.annotation.binaryAPI
28+
import scala.annotation.{binaryAPI, binaryAPIAccessor}
2929

3030
/** Provides methods to compare types.
3131
*/
@@ -158,7 +158,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
158158
private [this] var leftRoot: Type | Null = null
159159

160160
/** Are we forbidden from recording GADT constraints? */
161-
@binaryAPI private var frozenGadt = false
161+
@binaryAPIAccessor
162+
private var frozenGadt = false
162163
private inline def inFrozenGadt[T](inline op: T): T =
163164
inFrozenGadtIf(true)(op)
164165

@@ -189,7 +190,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
189190
inFrozenGadtIf(true)(inFrozenConstraint(op))
190191

191192
extension (sym: Symbol)
192-
@binaryAPI private inline def onGadtBounds(inline op: TypeBounds => Boolean): Boolean =
193+
@binaryAPIAccessor private inline def onGadtBounds(inline op: TypeBounds => Boolean): Boolean =
193194
val bounds = gadtBounds(sym)
194195
bounds != null && op(bounds)
195196

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ object PrepareInlineable {
5959

6060
def accessorNameOf(accessed: Symbol, site: Symbol)(using Context): TermName =
6161
val accName = InlineAccessorName(accessed.name.asTermName)
62-
if site.isExtensibleClass || accessed.isBinaryAPI then accName.expandedName(site)
62+
if site.isExtensibleClass || accessed.isBinaryAPIAccessor then accName.expandedName(site)
6363
else accName
6464

6565
/** A definition needs an accessor if it is private, protected, or qualified private
@@ -75,7 +75,7 @@ object PrepareInlineable {
7575
def needsAccessor(sym: Symbol)(using Context): Boolean =
7676
sym.isTerm &&
7777
(sym.isOneOf(AccessFlags) || sym.privateWithin.exists) &&
78-
(!sym.isBinaryAPI || sym.is(Private)) &&
78+
!sym.isBinaryAPI &&
7979
!(sym.isStableMember && sym.info.widenTermRefExpr.isInstanceOf[ConstantType]) &&
8080
!sym.isInlineMethod &&
8181
(Inlines.inInlineMethod || StagingLevel.level > 0)
@@ -104,13 +104,14 @@ object PrepareInlineable {
104104

105105
protected def unstableAccessorWarning(accessor: Symbol, accessed: Symbol, srcPos: SrcPos)(using Context): Unit =
106106
val accessorDefTree = accessorDef(accessor, accessed)
107+
val annot = if accessed.is(Private) then "@binaryAPIAccessor" else "@binaryAPI"
107108
val solution =
108109
if accessed.is(Private) then
109-
s"Annotate ${accessed.name} with `@binaryAPI` to generate a stable accessor."
110+
s"Annotate ${accessed.name} with `$annot` to generate a stable accessor."
110111
else
111-
s"Annotate ${accessed.name} with `@binaryAPI` to make it accessible."
112+
s"Annotate ${accessed.name} with `$annot` to make it accessible."
112113
val binaryCompat =
113-
s"""Adding @binaryAPI may break binary compatibility if a previous version of this
114+
s"""Adding $annot may break binary compatibility if a previous version of this
114115
|library was compiled with Scala 3.0-3.3, Binary compatibility should be checked
115116
|using MiMa. To keep binary you can add the following accessor to ${accessor.owner.showKind} ${accessor.owner.name.stripModuleClassSuffix}:
116117
| @binaryAPI private[${accessor.owner.name.stripModuleClassSuffix}] ${accessorDefTree.show}
@@ -133,7 +134,7 @@ object PrepareInlineable {
133134
}
134135
else
135136
val accessorTree = useAccessor(tree)
136-
if !tree.symbol.isBinaryAPI && tree.symbol != accessorTree.symbol then
137+
if !tree.symbol.isBinaryAPI && !tree.symbol.isBinaryAPIAccessor && tree.symbol != accessorTree.symbol then
137138
unstableAccessorWarning(accessorTree.symbol, tree.symbol, tree.srcPos)
138139
accessorTree
139140
case _ =>
@@ -245,7 +246,6 @@ object PrepareInlineable {
245246

246247
/** Create an inline accessor for this definition. */
247248
def makePrivateBinaryAPIAccessor(sym: Symbol)(using Context): Unit =
248-
assert(sym.is(Private))
249249
if !sym.is(Accessor) then
250250
val ref = tpd.ref(sym).asInstanceOf[RefTree]
251251
val accessor = InsertPrivateBinaryAPIAccessors.useAccessor(ref)

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import config.Feature.{migrateTo3, fewerBracesEnabled}
2121
import config.SourceVersion.`3.0`
2222
import reporting.{NoProfile, Profile, Message}
2323

24-
import scala.annotation.binaryAPI
24+
import scala.annotation.binaryAPIAccessor
2525

2626
import java.util.Objects
2727

@@ -1599,7 +1599,8 @@ object Scanners {
15991599
protected def coversIndent(w: IndentWidth): Boolean =
16001600
knownWidth != null && w == indentWidth
16011601

1602-
@binaryAPI private var myCommasExpected: Boolean = false
1602+
@binaryAPIAccessor
1603+
private var myCommasExpected: Boolean = false
16031604

16041605
inline def withCommasExpected[T](inline op: => T): T =
16051606
val saved = myCommasExpected

compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Decorators.{em, toMessage}
1919
import util.SourceFile
2020
import Utility._
2121

22-
import scala.annotation.binaryAPI
22+
import scala.annotation.binaryAPIAccessor
2323

2424
// XXX/Note: many/most of the functions in here are almost direct cut and pastes
2525
// from another file - scala.xml.parsing.MarkupParser, it looks like.
@@ -53,7 +53,7 @@ object MarkupParsers {
5353
override def getMessage: String = "input ended while parsing XML"
5454
}
5555

56-
class MarkupParser(@binaryAPI parser: Parser, final val preserveWS: Boolean)(using @binaryAPI c: Context) extends MarkupParserCommon {
56+
class MarkupParser(@binaryAPIAccessor parser: Parser, final val preserveWS: Boolean)(using @binaryAPIAccessor c: Context) extends MarkupParserCommon {
5757

5858
import Tokens.{ LBRACE, RBRACE }
5959

@@ -94,8 +94,8 @@ object MarkupParsers {
9494
var xEmbeddedBlock: Boolean = false
9595

9696
private var debugLastStartElement = List.empty[(Int, String)]
97-
@binaryAPI private def debugLastPos = debugLastStartElement.head._1
98-
@binaryAPI private def debugLastElem = debugLastStartElement.head._2
97+
@binaryAPIAccessor private def debugLastPos = debugLastStartElement.head._1
98+
@binaryAPIAccessor private def debugLastElem = debugLastStartElement.head._2
9999

100100
private def errorBraces() = {
101101
reportSyntaxError("in XML content, please use '}}' to express '}'")

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ import dotty.tools.dotc.util.SourcePosition
3131
import dotty.tools.dotc.ast.untpd.{MemberDef, Modifiers, PackageDef, RefTree, Template, TypeDef, ValOrDefDef}
3232
import cc.{CaptureSet, toCaptureSet, IllegalCaptureRef}
3333

34-
import scala.annotation.binaryAPI
34+
import scala.annotation.binaryAPIAccessor
3535

3636
class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
3737

3838
/** A stack of enclosing DefDef, TypeDef, or ClassDef, or ModuleDefs nodes */
3939
private var enclosingDef: untpd.Tree = untpd.EmptyTree
40-
@binaryAPI private var myCtx: Context = super.printerContext
40+
@binaryAPIAccessor private var myCtx: Context = super.printerContext
4141
private var printPos = ctx.settings.YprintPos.value
4242
private val printLines = ctx.settings.printLines.value
4343

compiler/src/dotty/tools/dotc/reporting/trace.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import core.*, Contexts.*, Decorators.*
88
import config.*
99
import printing.Formatting.*
1010

11-
import scala.annotation.binaryAPI
11+
import scala.annotation.binaryAPIAccessor
1212
import scala.compiletime.*
1313

1414
/** Exposes the {{{ trace("question") { op } }}} syntax.
@@ -77,9 +77,11 @@ trait TraceSyntax:
7777
inline def apply[T](inline question: String)(inline op: T)(using Context): T =
7878
apply[T](question, false)(op)
7979

80-
@binaryAPI private val alwaysToString = (x: Any) => String.valueOf(x)
80+
@binaryAPIAccessor
81+
private val alwaysToString = (x: Any) => String.valueOf(x)
8182

82-
@binaryAPI private def doTrace[T](question: => String,
83+
@binaryAPIAccessor
84+
private def doTrace[T](question: => String,
8385
printer: Printers.Printer = Printers.default,
8486
showOp: T => String)
8587
(op: => T)(using Context): T =

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,14 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
166166
++ sym.annotations)
167167
else
168168
val binaryAPIAnnotOpt = sym.getAnnotation(defn.BinaryAPIAnnot)
169+
val binaryAPIWithPrivateAccessorAnnotOpt = sym.getAnnotation(defn.BinaryAPIAccessorAnnot)
169170
if sym.is(Param) then
170171
sym.keepAnnotationsCarrying(thisPhase, Set(defn.ParamMetaAnnot), orNoneOf = defn.NonBeanMetaAnnots)
171172
else if sym.is(ParamAccessor) then
172173
// FIXME: copyAndKeepAnnotationsCarrying is dropping defn.BinaryAPIAnnot
173-
sym.keepAnnotationsCarrying(thisPhase, Set(defn.GetterMetaAnnot, defn.FieldMetaAnnot, defn.BinaryAPIAnnot))
174+
sym.keepAnnotationsCarrying(thisPhase, Set(defn.GetterMetaAnnot, defn.FieldMetaAnnot, defn.BinaryAPIAnnot, defn.BinaryAPIAccessorAnnot))
174175
for binaryAPIAnnot <- binaryAPIAnnotOpt do sym.addAnnotation(binaryAPIAnnot)
176+
for binaryAPIWithPrivateAccessorAnnot <- binaryAPIWithPrivateAccessorAnnotOpt do sym.addAnnotation(binaryAPIWithPrivateAccessorAnnot) // TODO is this one necessary?
175177
else
176178
sym.keepAnnotationsCarrying(thisPhase, Set(defn.GetterMetaAnnot, defn.FieldMetaAnnot), orNoneOf = defn.NonBeanMetaAnnots)
177179
if sym.isScala2Macro && !ctx.settings.XignoreScala2Macros.value then

compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools.dotc
22
package transform
33
package sjs
44

5-
import scala.annotation.binaryAPI
5+
import scala.annotation.binaryAPIAccessor
66
import scala.collection.mutable
77

88
import ast.tpd
@@ -1154,7 +1154,7 @@ object PrepJSInterop {
11541154
val name: String = "prepjsinterop"
11551155
val description: String = "additional checks and transformations for Scala.js"
11561156

1157-
private final class OwnerKind private (@binaryAPI private val baseKinds: Int) extends AnyVal {
1157+
private final class OwnerKind private (@binaryAPIAccessor private val baseKinds: Int) extends AnyVal {
11581158

11591159
inline def isBaseKind: Boolean =
11601160
Integer.lowestOneBit(baseKinds) == baseKinds && baseKinds != 0 // exactly 1 bit on

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,11 @@ object Checking {
530530
if sym.is(Enum) then fail(em"@binaryAPI cannot be used on enum definitions.")
531531
else if sym.isType && !sym.is(Module) && !(sym.is(Given) || sym.companionModule.is(Given)) then fail(em"@binaryAPI cannot be used on ${sym.showKind} definitions")
532532
else if !sym.owner.isClass && !(sym.is(Param) && sym.owner.isConstructor) then fail(em"@binaryAPI cannot be used on local definitions.")
533+
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`.")
534+
if sym.hasAnnotation(defn.BinaryAPIAccessorAnnot) then
535+
if sym.is(Enum) then fail(em"@binaryAPIAccessor cannot be used on enum definitions.")
536+
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")
537+
else if !sym.owner.isClass && !(sym.is(Param) && sym.owner.isConstructor) then fail(em"@binaryAPIAccessor cannot be used on local definitions.")
533538
if (sym.hasAnnotation(defn.NativeAnnot)) {
534539
if (!sym.is(Deferred))
535540
fail(NativeMembersMayNotHaveImplementation(sym))

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import util.Property
1515
import collection.mutable
1616
import Trees._
1717

18-
import scala.annotation.binaryAPI
18+
import scala.annotation.binaryAPIAccessor
1919

2020
/** A class that handles argument lifting. Argument lifting is needed in the following
2121
* scenarios:
@@ -165,7 +165,7 @@ object LiftComplex extends LiftComplex
165165
object LiftCoverage extends LiftImpure {
166166

167167
// Property indicating whether we're currently lifting the arguments of an application
168-
@binaryAPI private val LiftingArgs = new Property.Key[Boolean]
168+
@binaryAPIAccessor private val LiftingArgs = new Property.Key[Boolean]
169169

170170
private inline def liftingArgs(using Context): Boolean =
171171
ctx.property(LiftingArgs).contains(true)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import dotty.tools.dotc.util.Spans._
2323
import dotty.tools.dotc.util.Stats.record
2424
import dotty.tools.dotc.reporting.IllegalVariableInPatternAlternative
2525

26-
import scala.annotation.binaryAPI
26+
import scala.annotation.binaryAPIAccessor
2727
import scala.collection.mutable
2828

2929

@@ -215,7 +215,7 @@ trait QuotesAndSplices {
215215
})
216216

217217
object splitter extends tpd.TreeMap {
218-
@binaryAPI private var variance: Int = 1
218+
@binaryAPIAccessor private var variance: Int = 1
219219

220220
inline private def atVariance[T](v: Int)(op: => T): T = {
221221
val saved = variance

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,7 +2429,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24292429
}
24302430
val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym)
24312431
postProcessInfo(sym)
2432-
binaryAPI(sym)
2432+
binaryAPIAccessors(sym)
24332433
vdef1.setDefTree
24342434
}
24352435

@@ -2533,7 +2533,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25332533
val ddef2 = assignType(cpy.DefDef(ddef)(name, paramss1, tpt1, rhs1), sym)
25342534

25352535
postProcessInfo(sym)
2536-
binaryAPI(sym)
2536+
binaryAPIAccessors(sym)
25372537
ddef2.setDefTree
25382538
//todo: make sure dependent method types do not depend on implicits or by-name params
25392539
}
@@ -2548,8 +2548,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25482548
sym.setFlag(Erased)
25492549

25502550
/** Generate inline accessors for definitions annotated with @inlineAccessible */
2551-
def binaryAPI(sym: Symbol)(using Context): Unit =
2552-
if !ctx.isAfterTyper && !sym.is(Param) && sym.is(Private) && sym.hasAnnotation(defn.BinaryAPIAnnot) then
2551+
def binaryAPIAccessors(sym: Symbol)(using Context): Unit =
2552+
if !ctx.isAfterTyper && !sym.is(Param) && sym.hasAnnotation(defn.BinaryAPIAccessorAnnot) then
25532553
PrepareInlineable.makePrivateBinaryAPIAccessor(sym)
25542554

25552555
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = {

compiler/src/dotty/tools/dotc/util/ReusableInstance.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotty.tools.dotc.util
33
import scala.collection.mutable.ArrayBuffer
44
import scala.util.chaining._
55

6-
import scala.annotation.binaryAPI
6+
import scala.annotation.binaryAPIAccessor
77

88
/** A wrapper for a list of cached instances of a type `T`.
99
* The wrapper is recursion-reentrant: several instances are kept, so
@@ -16,9 +16,11 @@ import scala.annotation.binaryAPI
1616
*
1717
* Ported from scala.reflect.internal.util.ReusableInstance
1818
*/
19-
final class ReusableInstance[T <: AnyRef] private (@binaryAPI make: => T) {
20-
@binaryAPI private[this] val cache = new ArrayBuffer[T](ReusableInstance.InitialSize).tap(_.addOne(make))
21-
@binaryAPI private[this] var taken = 0
19+
final class ReusableInstance[T <: AnyRef] private (@binaryAPIAccessor make: => T) {
20+
@binaryAPIAccessor
21+
private[this] val cache = new ArrayBuffer[T](ReusableInstance.InitialSize).tap(_.addOne(make))
22+
@binaryAPIAccessor
23+
private[this] var taken = 0
2224

2325
inline def withInstance[R](action: T => R): R ={
2426
if (taken == cache.size)

0 commit comments

Comments
 (0)