Skip to content

Commit 50c5543

Browse files
committed
wipwipwip
1 parent f266c1e commit 50c5543

File tree

4 files changed

+38
-30
lines changed

4 files changed

+38
-30
lines changed

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

+20-15
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,10 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
220220
detectUsages walk auxConstructorBuf
221221
}
222222
}
223-
224-
def needsField(sym: Symbol): Boolean = typeNeedsStorage(enteringErasure(sym.info).resultType)
225-
def mustBeKept(sym: Symbol) = !(omittables(sym) || (sym.isValue && !sym.isMethod && (sym.owner.isTrait || !needsField(sym)))) // TODO: assert(!sym.owner.isTrait, sym.ownerChain)
223+
def mustBeKept(sym: Symbol) = !omittable(sym)
224+
// omit unused outers and non-memoized fields (I think we're no longer creating symbols for fields in traits, but still including backstop for now)
225+
def omittable(sym: Symbol) = (omittables(sym) ||
226+
(sym.isValue && !sym.isMethod && (!mustMemoize(sym) || sym.owner.isTrait))) // TODO: assert(!sym.owner.isTrait, sym.ownerChain)
226227

227228
} // OmittablesHelper
228229

@@ -606,7 +607,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
606607
// it goes before the superclass constructor call, otherwise it goes after.
607608
// A lazy val's effect is not moved to the constructor, as it is delayed.
608609
private def moveEffectToCtor(stat: ValOrDefDef): Boolean = {
609-
val fieldNeeded = needsField(stat.symbol)
610+
val memoized = mustMemoize(stat.symbol)
610611

611612
if (needsCtorEffect(stat)) {
612613
val rhs1 = intoConstructor(stat.symbol, stat.rhs)
@@ -618,7 +619,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
618619
else constrStatBuf
619620

620621
val effect =
621-
if (fieldNeeded) {
622+
if (memoized) {
622623
val assignSym =
623624
if (stat.symbol.isGetter) stat.symbol.asInstanceOf[MethodSymbol].referenced //setterIn(clazz, hasExpandedName = false) // not yet expanded -- see Mixin
624625
else stat.symbol
@@ -630,7 +631,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
630631
constrBufPart += effect
631632
}
632633

633-
fieldNeeded
634+
memoized
634635
}
635636

636637

@@ -695,12 +696,6 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
695696
// Triage all template definitions to go into defBuf/auxConstructorBuf, constrStatBuf, or constrPrefixBuf.
696697
for (stat <- stats) stat match {
697698
case dd@ DefDef(_,_,_,_,_,rhs) =>
698-
// We can't mark as deferred from the start, as it will be implemented automatically in the subclass
699-
// it should be marked deferred in bytecode, though
700-
if (inTrait && stat.symbol.isAccessor) {
701-
stat.symbol setFlag DEFERRED
702-
}
703-
704699
// methods with constant result type get literals as their body
705700
// all methods except the primary constructor go into template
706701
stat.symbol.tpe match {
@@ -710,9 +705,19 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
710705
if (stat.symbol.isPrimaryConstructor) ()
711706
else if (stat.symbol.isConstructor) auxConstructorBuf += stat
712707
// a concrete getter's RHS is treated like a ValDef (the actual field isn't emitted until Mixin augments the class that inherits the trait)
713-
else if (inTrait && stat.symbol.isGetter && (rhs ne EmptyTree)) {
714-
moveEffectToCtor(dd) // ignore whether we need a field -- it will be added in the inheriting class by Mixin
715-
defBuf += deriveDefDef(dd)(_ => EmptyTree)
708+
else if (inTrait) {
709+
// We can't mark as deferred from the start, as it will be implemented automatically in the subclass
710+
// it should be marked deferred in bytecode, though
711+
712+
defBuf +=
713+
if (stat.symbol.isGetter && (rhs ne EmptyTree)) {
714+
val memoized = moveEffectToCtor(dd)
715+
if (memoized) {
716+
stat.symbol setFlag DEFERRED
717+
deriveDefDef(dd)(_ => EmptyTree)
718+
}
719+
else stat
720+
} else stat
716721
}
717722
else defBuf += stat
718723
}

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

+14-12
Original file line numberDiff line numberDiff line change
@@ -257,19 +257,21 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
257257

258258
for (traitMember <- traitClass.info.decls) {
259259
println(traitMember)
260-
// accessors that need a field (and thus can't ultimately be concrete in a trait)
261-
if (isConcreteAccessor(traitMember)) {
262-
if (!isOverriddenAccessor(traitMember, clazz.info.baseClasses)) {
263-
mixinAccessorSym(traitClass, traitMember)
264-
265-
//if (traitMember.isLazy) initializer(mixedInAccessor) = traitMember
266-
267-
// mixin one field only (this method is called for both accessors)
268-
// don't mix in a field at all if it doesn't need storage
269-
if (traitMember.isGetter && typeNeedsStorage(traitMember.tpe.resultType))
270-
mixinFieldSym(traitMember)
260+
// accessors that need an implementation and a field
261+
if (traitMember.isAccessor) {
262+
if (traitMember hasFlag lateDEFERRED) {
263+
if (!isOverriddenAccessor(traitMember, clazz.info.baseClasses)) {
264+
mixinAccessorSym(traitClass, traitMember)
265+
266+
//if (traitMember.isLazy) initializer(mixedInAccessor) = traitMember
267+
268+
// mixin one field only (this method is called for both accessors)
269+
// don't mix in a field at all if it doesn't need storage
270+
if (traitMember.isGetter && mustMemoize(traitMember))
271+
mixinFieldSym(traitMember)
272+
}
273+
else devWarning(s"Overridden concrete accessor: ${traitMember.fullLocationString}")
271274
}
272-
else devWarning(s"Overridden concrete accessor: ${traitMember.fullLocationString}")
273275
} else if (traitMember.isSuperAccessor) {
274276
val sym = superSym(traitClass, traitMember.alias)
275277
if (sym ne NoSymbol) mixinSuperAccessorSym(traitMember, sym)

src/reflect/scala/reflect/internal/Definitions.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ trait Definitions extends api.StandardDefinitions {
236236
// Take into account annotations so that we keep annotated unit lazy val
237237
// to get better error message already from the cps plugin itself
238238
def isUnitType(tp: Type) = tp.typeSymbol == UnitClass && tp.annotations.isEmpty // you never know with annotations...
239-
def typeNeedsStorage(tp: Type) = !(tp.isInstanceOf[ConstantType] || isUnitType(tp))
239+
def memoizedType(tp: Type) = !(tp.isInstanceOf[ConstantType] || isUnitType(tp))
240+
def mustMemoize(sym: Symbol): Boolean = memoizedType(enteringErasure(sym.info).resultType)
240241

241242
def hasMultipleNonImplicitParamLists(member: Symbol): Boolean = hasMultipleNonImplicitParamLists(member.info)
242243
def hasMultipleNonImplicitParamLists(info: Type): Boolean = info match {

test/files/trait-defaults/fields.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ trait T {
3737
}
3838

3939
class C extends T {
40-
val abs = "abstract"
41-
val protabs = "abstract protected"
40+
final val abs = "abstract"
41+
final val protabs = "abstract protected"
4242
}
4343

4444
object Test extends C with App

0 commit comments

Comments
 (0)