scala/scala — pull request #3199 by retronym (2013-11-27 15:16:58+00:00)
Title: SI-5508 Eagerly create accessors for private[this] in traits

Currently, this is done late in the game as the Mixin tree transformer
treats the trait.

// Mixin#addLateInterfaceMembers
val getter = member.getter(clazz)
if (getter == NoSymbol) addMember(clazz, newGetter(member))

`addMember` mutates the type of the interface to add the getter.

However, if an inner class or anonymous function of the trait
has been flattened to a spot where it precedes the trait in the
enclosing packages info, this code hasn't had a chance to run,
and the lookup of the getter crashes as mixins postTransform
runs over a selection of the not-yet-materialized getter.

// Mixin#postTransform
case Select(qual, name) if sym.owner.isImplClass && !isStaticOnly(sym) =>
val iface = toInterface(sym.owner.tpe).typeSymbol
val ifaceGetter = sym getter iface

This commit removes the optimization to avoid creating accessors
in Namers for private[this] if the owner is a trait.

I can't spot a difference in the end result:

% cat sandbox/test.scala
trait T {
private val x: Int = 0
private[this] val y: Int = 0
}

% scalac-hash v2.10.3 sandbox/test.scala && javap -classpath . T
Compiled from "test.scala"
public interface T{
public abstract void T$_setter_$T$$x_$eq(int);
public abstract int T$$y();
public abstract void T$_setter_$T$$y_$eq(int);
public abstract int T$$x();
}

% qbin/scala sandbox/test.scala && javap -classpath . T
Compiled from "test.scala"
public interface T{
public abstract void T$_setter_$T$$x_$eq(int);
public abstract int T$$y();
public abstract void T$_setter_$T$$y_$eq(int);
public abstract int T$$x();
}

But we need to explore the history a little to figure out what
this change might break.