Skip to content

Commit 4f12b6d

Browse files
committed
emit needed members for fields in tratis from start
1 parent 8ccf754 commit 4f12b6d

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

src/compiler/scala/tools/nsc/transform/Mixin.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
172172

173173
/** Add all members to be mixed in into a (non-trait-) class
174174
* For every mixin trait T that is not also inherited by the superclass:
175-
* - for every abstract accessor in T, add a field and an implementation for that accessor
175+
* - for every abstract accessor in T, add a field (expanding its name if needed) and an implementation for that accessor
176176
* - for every super accessor in T, add an implementation of that accessor
177177
* - for every module in T, add a module
178178
*

src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ trait MethodSynthesis {
149149
val getter = Getter(tree)
150150
val getterSym = getter.createAndEnterSymbol()
151151
// Create the setter if necessary.
152-
if (mods.isMutable)
152+
if (getter.needsSetter)
153153
Setter(tree).createAndEnterSymbol()
154154

155155
// Create a field if the getter requires storage, otherwise,
156156
// the getter's abstract and the tree gets the getter's symbol.
157-
if (getter.noFieldNeeded) getterSym setPos tree.pos
157+
if (getter.noFieldHere) getterSym setPos tree.pos
158158
else enterStrictVal(tree)
159159
}
160160

@@ -302,14 +302,16 @@ trait MethodSynthesis {
302302
def derivedSym: Symbol = tree.symbol
303303
def derivedTree: Tree = EmptyTree
304304

305-
// - abstract vals have no value and thus need for a field (until they become concrete, potentially)
306-
// - traits store the RHS of the field in the getter;
307-
// constructors will move the assignment to the constructor, abstracting over the field using the field setter
308-
// - lazy or not, a val that stores a statically known value (unit / ConstantType) doesn't need a field either,
309-
// although the lazy value will need to consult the init bitmap to make sure the lazy compute method is only run once
310-
def noFieldNeeded = isDeferred ||
311-
derivedSym.owner.isTrait ||
312-
typeNeedsNoStorage(basisSym.tpe)
305+
// No field for these vals:
306+
// - abstract vals have no value we could store (until they become concrete, potentially)
307+
// - a concrete val with a statically known value (Unit / ConstantType)
308+
// performs its side effect according to lazy/strict semantics, but doesn't need to store its value
309+
// each access will "evaluate" the RHS (a literal) again
310+
// - concrete vals in traits don't yield a field here either (their getter's RHS has the initial value)
311+
// Constructors will move the assignment to the constructor, abstracting over the field using the field setter,
312+
// and Mixin will add a field to the class that mixes in the trait, implementing the accessors in terms of it
313+
def noFieldHere = nothingToMemoize || derivedSym.owner.isTrait
314+
protected def nothingToMemoize = isDeferred || typeNeedsNoStorage(basisSym.tpe)
313315

314316
def isSetter = false
315317
def isDeferred = mods.isDeferred
@@ -334,7 +336,7 @@ trait MethodSynthesis {
334336
}
335337
}
336338
sealed trait DerivedGetter extends DerivedFromValDef {
337-
// TODO
339+
def needsSetter = mods.isMutable || (derivedSym.owner.isTrait && !nothingToMemoize)
338340
}
339341
sealed trait DerivedSetter extends DerivedFromValDef {
340342
override def isSetter = true
@@ -343,7 +345,7 @@ trait MethodSynthesis {
343345
case _ => NoSymbol
344346
}
345347
private def setterRhs =
346-
if (noFieldNeeded || derivedSym.isOverloaded) EmptyTree
348+
if (noFieldHere || derivedSym.isOverloaded) EmptyTree
347349
else Assign(fieldSelection, Ident(setterParam))
348350

349351
private def setterDef = DefDef(derivedSym, setterRhs)
@@ -386,7 +388,8 @@ trait MethodSynthesis {
386388
}
387389
case class Getter(tree: ValDef) extends BaseGetter(tree) {
388390
override def derivedSym = if (isDeferred) basisSym else basisSym.getterIn(enclClass)
389-
private def derivedRhs = if (noFieldNeeded) tree.rhs else fieldSelection
391+
private def derivedRhs = if (noFieldHere) tree.rhs else fieldSelection
392+
390393
private def derivedTpt = {
391394
// For existentials, don't specify a type for the getter, even one derived
392395
// from the symbol! This leads to incompatible existentials for the field and
@@ -434,7 +437,7 @@ trait MethodSynthesis {
434437
override def derivedTree: DefDef = {
435438
val ValDef(_, _, tpt0, rhs0) = tree
436439
val rhs1 = context.unit.transformed.getOrElse(rhs0, rhs0)
437-
val body = if (noFieldNeeded) rhs1
440+
val body = if (noFieldHere) rhs1
438441
else gen.mkAssignAndReturn(basisSym, rhs1)
439442

440443
derivedSym setPos tree.pos // cannot set it at createAndEnterSymbol because basisSym can possibly still have NoPosition
@@ -465,7 +468,7 @@ trait MethodSynthesis {
465468
override def keepClean = !mods.isParamAccessor
466469

467470
override def derivedSym =
468-
if (noFieldNeeded) NoSymbol
471+
if (noFieldHere) NoSymbol
469472
else super.derivedSym
470473

471474
override def derivedTree = (

0 commit comments

Comments
 (0)