summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-07-31 13:38:46 +0000
committerMartin Odersky <odersky@gmail.com>2008-07-31 13:38:46 +0000
commit076db04123bf5d983c45029fc3338861b0c4410f (patch)
tree9a8e2eaafd6e62abae0d9caf94b7bc1dec56543a
parent9cfe5e961e5fe9d13b4029cf78b2253c85d3f503 (diff)
downloadscala-076db04123bf5d983c45029fc3338861b0c4410f.tar.gz
scala-076db04123bf5d983c45029fc3338861b0c4410f.tar.bz2
scala-076db04123bf5d983c45029fc3338861b0c4410f.zip
-Xexperimental changes for #1093
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala11
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala21
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala54
-rw-r--r--test/files/pos/t1147.scala6
6 files changed, 84 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 _ =>
diff --git a/test/files/pos/t1147.scala b/test/files/pos/t1147.scala
new file mode 100644
index 0000000000..e320571b24
--- /dev/null
+++ b/test/files/pos/t1147.scala
@@ -0,0 +1,6 @@
+class App(arg: String) {
+ @deprecated def this() {
+ this("foo")
+ }
+}
+