-Xexperimental changes for #1093

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@15656 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
odersky 2008-07-31 13:38:46 +00:00
parent fde6e8f5ba
commit 4762849482
6 changed files with 84 additions and 20 deletions

View File

@ -71,6 +71,7 @@ trait StdNames {
val LOCALDUMMY_PREFIX_STRING = "<local "
val SUPER_PREFIX_STRING = "super$"
val EXPAND_SEPARATOR_STRING = "$$"
val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
val TUPLE_FIELD_PREFIX_STRING = "_"
val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
@ -96,6 +97,7 @@ trait StdNames {
def isLocalName(name: Name) = name.endsWith(LOCAL_SUFFIX)
def isSetterName(name: Name) = name.endsWith(SETTER_SUFFIX)
def isLocalDummyName(name: Name) = name.startsWith(LOCALDUMMY_PREFIX)
def isTraitSetterName(name: Name) = isSetterName(name) && name.pos(TRAIT_SETTER_SEPARATOR_STRING) < name.length
def isOpAssignmentName(name: Name) =
name(name.length - 1) == '=' &&
isOperatorCharacter(name(0)) &&
@ -111,7 +113,8 @@ trait StdNames {
chtp == Character.MATH_SYMBOL || chtp == Character.OTHER_SYMBOL
}
/** If `name' is an expandedName, the original name. Otherwise `name' itself.
/** If `name' is an expandedName name, the original name.
* Otherwise `name' itself.
* @see Symbol.expandedName
*/
def originalName(name: Name): Name = {
@ -139,7 +142,11 @@ trait StdNames {
}
def setterToGetter(name: Name): Name = {
name.subName(0, name.length - SETTER_SUFFIX.length)
val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
if (p < name.length)
setterToGetter(name.subName(p + TRAIT_SETTER_SEPARATOR_STRING.length, name.length))
else
name.subName(0, name.length - SETTER_SUFFIX.length)
}
def getterName(name: Name): Name =

View File

@ -45,7 +45,7 @@ trait Symbols {
var rawflags: Long = 0
private var rawpos = initPos
val id = { ids += 1; ids }
// assert(id != 5413, initName+"/"+initOwner)
// assert(id != 7498, initName+"/"+initOwner)
var validTo: Period = NoPeriod
@ -987,11 +987,11 @@ trait Symbols {
/** The symbol overridden by this symbol in given class `ofclazz' */
final def overriddenSymbol(ofclazz: Symbol): Symbol =
matchingSymbol(ofclazz, owner.thisType)
if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, owner.thisType)
/** The symbol overriding this symbol in given subclass `ofclazz' */
final def overridingSymbol(ofclazz: Symbol): Symbol =
matchingSymbol(ofclazz, ofclazz.thisType)
if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType)
final def allOverriddenSymbols: List[Symbol] =
if (owner.isClass && !owner.info.baseClasses.isEmpty)
@ -1035,8 +1035,13 @@ trait Symbols {
}
/** The setter of this value or getter definition, or NoSymbol if none exists */
final def setter(base: Symbol): Symbol =
base.info.decl(nme.getterToSetter(nme.getterName(name))) filter (_.hasFlag(ACCESSOR))
final def setter(base: Symbol): Symbol = setter(base, false)
final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
var sname = nme.getterToSetter(nme.getterName(name))
if (hasExpandedName) sname = base.expandedSetterName(sname)
base.info.decl(sname) filter (_.hasFlag(ACCESSOR))
}
/** The case module corresponding to this case class
* @pre case class is a member of some other class or package
@ -1087,6 +1092,9 @@ trait Symbols {
}
}
def expandedSetterName(simpleSetterName: Name): Name =
newTermName(fullNameString('$') + nme.TRAIT_SETTER_SEPARATOR_STRING + simpleSetterName)
/** The expanded name of `name' relative to this class as base
*/
def expandedName(name: Name): Name = {
@ -1206,7 +1214,7 @@ trait Symbols {
if (isClassConstructor) owner.simpleName.decode+idString else nameString))
/** String representation of location. */
final def locationString: String =
def locationString: String =
if (owner.isClass &&
((!owner.isAnonymousClass &&
!owner.isRefinementClass &&
@ -1592,6 +1600,7 @@ trait Symbols {
this
}
override def defString: String = toString
override def locationString: String = ""
override def enclClass: Symbol = this
override def toplevelClass: Symbol = this
override def enclMethod: Symbol = this

View File

@ -3683,7 +3683,7 @@ A type's typeSymbol should never be inspected directly.
}
/** A function implementing `tp1' matches `tp2' */
private def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = (tp1, tp2) match {
def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = (tp1, tp2) match {
case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
matchingParams(pts1, pts2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
matchesType(res1, res2, alwaysMatchSimple) &&

View File

@ -312,6 +312,16 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
private def isSeqClass(sym: Symbol) =
(SeqClass isNonBottomSubClass sym) && (sym != ObjectClass)
/** The symbol which is called by a bridge;
* @pre phase > erasure
*/
def bridgedSym(bridge: Symbol) =
bridge.owner.info.nonPrivateDecl(bridge.name) suchThat {
sym => !(sym hasFlag BRIDGE) &&
matchesType(sym.tpe, bridge.tpe, true) &&
sym.tpe.resultType <:< bridge.tpe.resultType
}
// -------- boxing/unboxing --------------------------------------------------------
override def newTyper(context: Context) = new Eraser(context)

View File

@ -114,6 +114,20 @@ abstract class Mixin extends InfoTransform {
// --------- type transformation -----------------------------------------------
def isConcreteAccessor(member: Symbol) =
(member hasFlag ACCESSOR) &&
(!(member hasFlag DEFERRED) || (member hasFlag lateDEFERRED))
/** Is member overridden (either directly or via a bridge) in base class sequence `bcs'? */
def isOverriddenAccessor(member: Symbol, bcs: List[Symbol]): Boolean = atPhase(ownPhase) {
def hasOverridingAccessor(clazz: Symbol) = {
clazz.info.nonPrivateDecl(member.name).alternatives.exists(
sym => isConcreteAccessor(sym) && matchesType(sym.tpe, member.tpe, true))
}
bcs.head != member.owner &&
(hasOverridingAccessor(bcs.head) || isOverriddenAccessor(member, bcs.tail))
}
/** Add given member to given class, and mark member as mixed-in.
*/
def addMember(clazz: Symbol, member: Symbol): Symbol = {
@ -122,6 +136,9 @@ abstract class Mixin extends InfoTransform {
member setFlag MIXEDIN
}
def needsExpandedSetterName(field: Symbol) =
settings.Xexperimental.value && !field.hasFlag(LAZY | MUTABLE)
/** Add getters and setters for all non-module fields of an implementation
* class to its interface unless they are already present. This is done
* only once per class. The mixedin flag is used to remember whether late
@ -144,10 +161,14 @@ abstract class Mixin extends InfoTransform {
/** Create a new setter. Setters are never private or local. They are
* always accessors and deferred. */
def newSetter(field: Symbol): Symbol =
clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name)))
def newSetter(field: Symbol): Symbol = {
val setterName = nme.getterToSetter(nme.getterName(field.name))
val setter = clazz.newMethod(field.pos, setterName)
.setFlag(field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | lateDEFERRED)
.setInfo(MethodType(List(field.info), UnitClass.tpe))
if (needsExpandedSetterName(field)) setter.name = clazz.expandedSetterName(setter.name)
setter
}
clazz.info // make sure info is up to date, so that implClass is set.
val impl = implClass(clazz)
@ -162,7 +183,7 @@ abstract class Mixin extends InfoTransform {
val getter = member.getter(clazz)
if (getter == NoSymbol) addMember(clazz, newGetter(member))
if (!member.tpe.isInstanceOf[ConstantType] && !member.hasFlag(LAZY)) {
val setter = member.setter(clazz)
val setter = member.setter(clazz, needsExpandedSetterName(member))
if (setter == NoSymbol) addMember(clazz, newSetter(member))
}
}
@ -221,14 +242,9 @@ abstract class Mixin extends InfoTransform {
*/
def mixinTraitMembers(mixinClass: Symbol) {
// For all members of a trait's interface do:
def isConcreteAccessor(member: Symbol) =
(member hasFlag ACCESSOR) &&
(!(member hasFlag DEFERRED) || (member hasFlag lateDEFERRED))
def isOverridden(member: Symbol) =
isConcreteAccessor(member.overridingSymbol(clazz))
for (val member <- mixinClass.info.decls.toList) {
if (isConcreteAccessor(member)) {
if (isOverridden(member)) {
if (isOverriddenAccessor(member, clazz.info.baseClasses)) {
if (settings.debug.value) println("!!! is overridden val: "+member)
} else {
// mixin field accessors
@ -791,7 +807,17 @@ abstract class Mixin extends InfoTransform {
}
}
if (sym.isSetter) {
accessedRef match {
val isOverriddenSetter =
settings.Xexperimental.value && nme.isTraitSetterName(sym.name) && {
sym.allOverriddenSymbols match {
case other :: _ =>
isOverriddenAccessor(other.getter(other.owner), clazz.info.baseClasses)
case _ =>
false
}
}
if (isOverriddenSetter) Literal(())
else accessedRef match {
case Literal(_) => accessedRef
case _ =>
val init = Assign(accessedRef, Ident(vparams.head))
@ -950,7 +976,13 @@ abstract class Mixin extends InfoTransform {
// setter in the interface.
localTyper.typed {
atPos(tree.pos) {
Apply(Select(qual, lhs.symbol.setter(toInterface(lhs.symbol.owner.tpe).typeSymbol)) setPos lhs.pos, List(rhs))
Apply(
Select(
qual,
lhs.symbol.setter(
toInterface(lhs.symbol.owner.tpe).typeSymbol,
needsExpandedSetterName(lhs.symbol))) setPos lhs.pos,
List(rhs))
}
}
case _ =>

View File

@ -0,0 +1,6 @@
class App(arg: String) {
@deprecated def this() {
this("foo")
}
}