Skip to content

Commit 90d4876

Browse files
committed
Pass data reader aroung to avoid accidental capture
1 parent a8234b8 commit 90d4876

File tree

1 file changed

+65
-70
lines changed

1 file changed

+65
-70
lines changed

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 65 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ class ClassfileParser(
6262
import ClassfileConstants._
6363
import ClassfileParser._
6464

65-
protected var in: DataReader = _
66-
6765
protected val staticModule: Symbol = moduleRoot.sourceModule(using ictx)
6866

6967
protected val instanceScope: MutableScope = newScope // the scope of all instance definitions
@@ -84,7 +82,7 @@ class ClassfileParser(
8482
throw new IOException(s"class file '${classfile.canonicalPath}' has location not matching its contents: contains class $className")
8583

8684
def run()(using Context): Option[Embedded] = try ctx.base.reusableDataReader.using { reader =>
87-
this.in = reader.reset(classfile)
85+
implicit val in: DataReader = reader.reset(classfile)
8886

8987
report.debuglog("[class] >> " + classRoot.fullName)
9088
parseHeader()
@@ -93,13 +91,13 @@ class ClassfileParser(
9391
}
9492
catch {
9593
case e: RuntimeException =>
96-
if (ctx.debug) e.printStackTrace()
94+
e.printStackTrace()
9795
throw new IOException(
9896
i"""class file ${classfile.canonicalPath} is broken, reading aborted with ${e.getClass}
9997
|${Option(e.getMessage).getOrElse("")}""")
10098
}
10199

102-
private def parseHeader(): Unit = {
100+
private def parseHeader()(using in: DataReader): Unit = {
103101
val magic = in.nextInt
104102
if (magic != JAVA_MAGIC)
105103
throw new IOException(s"class file '${classfile}' has wrong magic number 0x${toHexString(magic)}, should be 0x${toHexString(JAVA_MAGIC)}")
@@ -120,7 +118,7 @@ class ClassfileParser(
120118

121119
var sawPrivateConstructor: Boolean = false
122120

123-
def parseClass()(using Context): Option[Embedded] = {
121+
def parseClass()(using ctx: Context, in: DataReader): Option[Embedded] = {
124122
val jflags = in.nextChar
125123
val isAnnotation = hasAnnotation(jflags)
126124
val sflags = classTranslation.flags(jflags)
@@ -220,7 +218,7 @@ class ClassfileParser(
220218
}
221219
}
222220

223-
def parseMember(method: Boolean)(using Context): Unit = {
221+
def parseMember(method: Boolean)(using ctx: Context, in: DataReader): Unit = {
224222
val start = indexCoord(in.bp)
225223
val jflags = in.nextChar
226224
val sflags =
@@ -241,70 +239,67 @@ class ClassfileParser(
241239
val memberCompleter: LazyType = new LazyType {
242240

243241
def complete(denot: SymDenotation)(using Context): Unit = ctx.base.reusableDataReader.using { reader =>
244-
val oldIn = in
245-
in = reader.reset(classfile)
246-
try {
247-
in.bp = denot.symbol.coord.toIndex
248-
val sym = denot.symbol
249-
val jflags = in.nextChar
250-
val isEnum = (jflags & JAVA_ACC_ENUM) != 0
251-
val name = pool.getName(in.nextChar)
252-
val isConstructor = name eq nme.CONSTRUCTOR
253-
254-
/** Strip leading outer param from constructor and trailing access tag for
255-
* private inner constructors.
256-
*/
257-
def normalizeConstructorParams() = innerClasses.get(currentClassName) match {
258-
case Some(entry) if !isStatic(entry.jflags) =>
259-
val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
260-
var normalizedParamNames = paramNames.tail
261-
var normalizedParamTypes = paramTypes.tail
262-
if ((jflags & JAVA_ACC_SYNTHETIC) != 0) {
263-
// SI-7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
264-
// are added when an inner class needs to access a private constructor.
265-
normalizedParamNames = paramNames.dropRight(1)
266-
normalizedParamTypes = paramTypes.dropRight(1)
267-
}
268-
denot.info = mt.derivedLambdaType(normalizedParamNames, normalizedParamTypes, resultType)
269-
case _ =>
270-
}
242+
implicit val in: DataReader = reader.reset(classfile)
271243

272-
/** Make return type of constructor be the enclosing class type,
273-
* and make constructor type polymorphic in the type parameters of the class
274-
*/
275-
def normalizeConstructorInfo() = {
276-
val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef))
277-
278-
def resultType(tpe: Type): Type = tpe match {
279-
case mt @ MethodType(paramNames) => mt.derivedLambdaType(paramNames, mt.paramInfos, rt)
280-
case pt : PolyType => pt.derivedLambdaType(pt.paramNames, pt.paramInfos, resultType(pt.resType))
244+
in.bp = denot.symbol.coord.toIndex
245+
val sym = denot.symbol
246+
val jflags = in.nextChar
247+
val isEnum = (jflags & JAVA_ACC_ENUM) != 0
248+
val name = pool.getName(in.nextChar)
249+
val isConstructor = name eq nme.CONSTRUCTOR
250+
251+
/** Strip leading outer param from constructor and trailing access tag for
252+
* private inner constructors.
253+
*/
254+
def normalizeConstructorParams() = innerClasses.get(currentClassName) match {
255+
case Some(entry) if !isStatic(entry.jflags) =>
256+
val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
257+
var normalizedParamNames = paramNames.tail
258+
var normalizedParamTypes = paramTypes.tail
259+
if ((jflags & JAVA_ACC_SYNTHETIC) != 0) {
260+
// SI-7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
261+
// are added when an inner class needs to access a private constructor.
262+
normalizedParamNames = paramNames.dropRight(1)
263+
normalizedParamTypes = paramTypes.dropRight(1)
281264
}
265+
denot.info = mt.derivedLambdaType(normalizedParamNames, normalizedParamTypes, resultType)
266+
case _ =>
267+
}
282268

283-
denot.info = resultType(denot.info)
284-
addConstructorTypeParams(denot)
269+
/** Make return type of constructor be the enclosing class type,
270+
* and make constructor type polymorphic in the type parameters of the class
271+
*/
272+
def normalizeConstructorInfo() = {
273+
val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef))
274+
275+
def resultType(tpe: Type): Type = tpe match {
276+
case mt @ MethodType(paramNames) => mt.derivedLambdaType(paramNames, mt.paramInfos, rt)
277+
case pt : PolyType => pt.derivedLambdaType(pt.paramNames, pt.paramInfos, resultType(pt.resType))
285278
}
286279

287-
val isVarargs = denot.is(Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0
288-
denot.info = pool.getType(in.nextChar, isVarargs)
289-
if (isConstructor) normalizeConstructorParams()
290-
denot.info = translateTempPoly(parseAttributes(sym, denot.info, isVarargs))
291-
if (isConstructor) normalizeConstructorInfo()
280+
denot.info = resultType(denot.info)
281+
addConstructorTypeParams(denot)
282+
}
292283

293-
if (ctx.explicitNulls) denot.info = JavaNullInterop.nullifyMember(denot.symbol, denot.info, isEnum)
284+
val isVarargs = denot.is(Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0
285+
denot.info = pool.getType(in.nextChar, isVarargs)
286+
if (isConstructor) normalizeConstructorParams()
287+
denot.info = translateTempPoly(parseAttributes(sym, denot.info, isVarargs))
288+
if (isConstructor) normalizeConstructorInfo()
294289

295-
// seal java enums
296-
if (isEnum) {
297-
val enumClass = sym.owner.linkedClass
298-
if (!enumClass.exists)
299-
report.warning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.")
300-
else {
301-
if (!enumClass.is(Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
302-
enumClass.addAnnotation(Annotation.Child(sym, NoSpan))
303-
}
290+
if (ctx.explicitNulls) denot.info = JavaNullInterop.nullifyMember(denot.symbol, denot.info, isEnum)
291+
292+
// seal java enums
293+
if (isEnum) {
294+
val enumClass = sym.owner.linkedClass
295+
if (!enumClass.exists)
296+
report.warning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.")
297+
else {
298+
if (!enumClass.is(Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
299+
enumClass.addAnnotation(Annotation.Child(sym, NoSpan))
304300
}
305301
}
306-
finally
307-
in = oldIn
302+
308303
}
309304
}
310305

@@ -504,7 +499,7 @@ class ClassfileParser(
504499
}
505500
// sigToType
506501

507-
def parseAnnotArg(skip: Boolean = false)(using Context): Option[untpd.Tree] = {
502+
def parseAnnotArg(skip: Boolean = false)(using ctx: Context, in: DataReader): Option[untpd.Tree] = {
508503

509504
// If we encounter an empty array literal, we need the type of the corresponding
510505
// parameter to properly type it, but that would require forcing the annotation
@@ -569,7 +564,7 @@ class ClassfileParser(
569564
/** Parse and return a single annotation. If it is malformed,
570565
* return None.
571566
*/
572-
def parseAnnotation(attrNameIndex: Char, skip: Boolean = false)(using Context): Option[ClassfileAnnotation] = try {
567+
def parseAnnotation(attrNameIndex: Char, skip: Boolean = false)(using ctx: Context, in: DataReader): Option[ClassfileAnnotation] = try {
573568
val attrType = pool.getType(attrNameIndex)
574569
attrType match
575570
case tp: TypeRef =>
@@ -608,7 +603,7 @@ class ClassfileParser(
608603
None // ignore malformed annotations
609604
}
610605

611-
def parseAttributes(sym: Symbol, symtype: Type, isVarargs: Boolean = false)(using Context): Type = {
606+
def parseAttributes(sym: Symbol, symtype: Type, isVarargs: Boolean = false)(using ctx: Context, in: DataReader): Type = {
612607
var newType = symtype
613608

614609
def parseAttribute(): Unit = {
@@ -749,7 +744,7 @@ class ClassfileParser(
749744
* Restores the old `bp`.
750745
* @return true iff classfile is from Scala, so no Java info needs to be read.
751746
*/
752-
def unpickleOrParseInnerClasses()(using Context): Option[Embedded] = {
747+
def unpickleOrParseInnerClasses()(using ctx: Context, in: DataReader): Option[Embedded] = {
753748
val oldbp = in.bp
754749
try {
755750
skipSuperclasses()
@@ -985,21 +980,21 @@ class ClassfileParser(
985980
}
986981
}
987982

988-
def skipAttributes(): Unit = {
983+
def skipAttributes()(using in: DataReader): Unit = {
989984
val attrCount = in.nextChar
990985
for (i <- 0 until attrCount) {
991986
in.skip(2); in.skip(in.nextInt)
992987
}
993988
}
994989

995-
def skipMembers(): Unit = {
990+
def skipMembers()(using in: DataReader): Unit = {
996991
val memberCount = in.nextChar
997992
for (i <- 0 until memberCount) {
998993
in.skip(6); skipAttributes()
999994
}
1000995
}
1001996

1002-
def skipSuperclasses(): Unit = {
997+
def skipSuperclasses()(using in: DataReader): Unit = {
1003998
in.skip(2) // superclass
1004999
val ifaces = in.nextChar
10051000
in.skip(2 * ifaces)
@@ -1035,7 +1030,7 @@ class ClassfileParser(
10351030
requiredModule(name.dropRight(1))
10361031
else classNameToSymbol(name)
10371032

1038-
class ConstantPool {
1033+
class ConstantPool(using in: DataReader) {
10391034
private val len = in.nextChar
10401035
private val starts = new Array[Int](len)
10411036
private val values = new Array[AnyRef](len)

0 commit comments

Comments
 (0)