diff options
author | Martin Odersky <odersky@gmail.com> | 2008-07-31 13:38:46 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-07-31 13:38:46 +0000 |
commit | 076db04123bf5d983c45029fc3338861b0c4410f (patch) | |
tree | 9a8e2eaafd6e62abae0d9caf94b7bc1dec56543a /src/compiler | |
parent | 9cfe5e961e5fe9d13b4029cf78b2253c85d3f503 (diff) | |
download | scala-076db04123bf5d983c45029fc3338861b0c4410f.tar.gz scala-076db04123bf5d983c45029fc3338861b0c4410f.tar.bz2 scala-076db04123bf5d983c45029fc3338861b0c4410f.zip |
-Xexperimental changes for #1093
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 21 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 54 |
5 files changed, 78 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index aa8b0710fa..8385b13dfb 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -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 = diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 93b6342177..b5df166790 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -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 diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 0ac0519f6b..107a221894 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -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) && diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index a9baef9176..4c65f76c97 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -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) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 4022c38dde..f22cde9669 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -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 _ => |