Skip to content

Commit 1f23771

Browse files
committed
LazyVals: do not share offsets between companions.
There used to be a rare test when companion class and companion object would have gotten the very same offset, causing undefined behaviour in runtime.
1 parent 5e48558 commit 1f23771

File tree

1 file changed

+9
-12
lines changed

1 file changed

+9
-12
lines changed

src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import dotty.tools.dotc.core.SymDenotations.SymDenotation
2626
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer, DenotTransformer}
2727
import Erasure.Boxing.adaptToType
2828

29-
class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with NeedsCompanions {
29+
class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
3030
import LazyVals._
3131

3232
import tpd._
@@ -49,11 +49,6 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with Nee
4949
* before this phase starts processing same tree */
5050
override def runsAfter = Set(classOf[Mixin])
5151

52-
def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean = {
53-
def hasLazyVal(cls: ClassSymbol) = cls.info.decls.exists(_.is(Flags.Lazy))
54-
hasLazyVal(cls) || cls.mixins.exists(hasLazyVal)
55-
}
56-
5752
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
5853
transformLazyVal(tree)
5954

@@ -341,26 +336,28 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with Nee
341336
val tpe = x.tpe.widen.resultType.widen
342337
val claz = x.symbol.owner.asClass
343338
val thizClass = Literal(Constant(claz.info))
344-
val companion = claz.companionModule
345339
val helperModule = ctx.requiredModule("dotty.runtime.LazyVals")
346340
val getOffset = Select(ref(helperModule), lazyNme.RLazyVals.getOffset)
347341
var offsetSymbol: TermSymbol = null
348342
var flag: Tree = EmptyTree
349343
var ord = 0
350344

345+
def offsetName(id: Int) = (StdNames.nme.LAZY_FIELD_OFFSET + (if(x.symbol.owner.is(Flags.Module)) "_m_" else "") + id.toString).toTermName
346+
351347
// compute or create appropriate offsetSymol, bitmap and bits used by current ValDef
352-
appendOffsetDefs.get(companion.moduleClass) match {
348+
appendOffsetDefs.get(claz) match {
353349
case Some(info) =>
354350
val flagsPerLong = (64 / dotty.runtime.LazyVals.BITS_PER_LAZY_VAL).toInt
355351
info.ord += 1
356352
ord = info.ord % flagsPerLong
357353
val id = info.ord / flagsPerLong
354+
val offsetById = offsetName(id)
358355
if (ord != 0) { // there are unused bits in already existing flag
359-
offsetSymbol = companion.moduleClass.info.decl((StdNames.nme.LAZY_FIELD_OFFSET + id.toString).toTermName)
356+
offsetSymbol = claz.moduleClass.info.decl(offsetById)
360357
.suchThat(sym => (sym is Flags.Synthetic) && sym.isTerm)
361358
.symbol.asTerm
362359
} else { // need to create a new flag
363-
offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + id.toString).toTermName, Flags.Synthetic, defn.LongType).enteredAfter(this)
360+
offsetSymbol = ctx.newSymbol(claz, offsetById, Flags.Synthetic, defn.LongType).enteredAfter(this)
364361
offsetSymbol.addAnnotation(Annotation(defn.ScalaStaticAnnot))
365362
val flagName = (StdNames.nme.BITMAP_PREFIX + id.toString).toTermName
366363
val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
@@ -370,13 +367,13 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with Nee
370367
}
371368

372369
case None =>
373-
offsetSymbol = ctx.newSymbol(companion.moduleClass, (StdNames.nme.LAZY_FIELD_OFFSET + "0").toTermName, Flags.Synthetic, defn.LongType).enteredAfter(this)
370+
offsetSymbol = ctx.newSymbol(claz, offsetName(0), Flags.Synthetic, defn.LongType).enteredAfter(this)
374371
offsetSymbol.addAnnotation(Annotation(defn.ScalaStaticAnnot))
375372
val flagName = (StdNames.nme.BITMAP_PREFIX + "0").toTermName
376373
val flagSymbol = ctx.newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
377374
flag = ValDef(flagSymbol, Literal(Constants.Constant(0L)))
378375
val offsetTree = ValDef(offsetSymbol, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString))))
379-
appendOffsetDefs += (companion.moduleClass -> new OffsetInfo(List(offsetTree), ord))
376+
appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord))
380377
}
381378

382379
val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName

0 commit comments

Comments
 (0)