-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:
parent
fde6e8f5ba
commit
4762849482
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 _ =>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class App(arg: String) {
|
||||
@deprecated def this() {
|
||||
this("foo")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue