summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--classpath.SAMPLE5
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala2
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala11
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala34
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala141
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala3
-rw-r--r--src/library/scala/collection/immutable/List.scala2
-rw-r--r--src/library/scala/collection/mutable/Stack.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashMap.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParVector.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala6
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashMap.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParTrieMap.scala2
-rw-r--r--test/files/run/finalvar.check6
-rw-r--r--test/files/run/finalvar.flags1
-rw-r--r--test/files/run/finalvar.scala37
-rw-r--r--test/pending/pos/t1476.scala23
-rw-r--r--test/pending/pos/t5626.scala12
-rw-r--r--test/pending/run/t5629.check2
-rw-r--r--test/pending/run/t5629.scala25
27 files changed, 262 insertions, 95 deletions
diff --git a/classpath.SAMPLE b/classpath.SAMPLE
index 69c2baeba7..9e607a41d9 100644
--- a/classpath.SAMPLE
+++ b/classpath.SAMPLE
@@ -3,10 +3,9 @@
<classpathentry kind="src" path="src/compiler"/>
<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry exported="true" kind="lib" path="lib/msil.jar"/>
+ <classpathentry kind="lib" path="lib/msil.jar"/>
<classpathentry kind="lib" path="lib/jline.jar"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry exported="true" kind="lib" path="lib/fjbg.jar"/>
+ <classpathentry kind="lib" path="lib/fjbg.jar"/>
<classpathentry kind="lib" path="lib/forkjoin.jar"/>
<classpathentry kind="lib" path="lib/ant/ant.jar"/>
<classpathentry kind="output" path="build/quick/classes/compiler"/>
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index 3110d73461..ce1c8d0908 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -84,7 +84,7 @@ import scala.collection.{ mutable, immutable }
*/
class ModifierFlags {
final val IMPLICIT = 0x00000200
- final val FINAL = 0x00000020
+ final val FINAL = 0x00000020 // May not be overridden. Note that java final implies much more than scala final.
final val PRIVATE = 0x00000004
final val PROTECTED = 0x00000001
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index b58a0ef7d5..bb11ca634a 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -55,6 +55,12 @@ abstract class SymbolTable extends api.Universe
log(msg + ": " + result)
result
}
+ private[scala] def logResultIf[T](msg: String, cond: T => Boolean)(result: T): T = {
+ if (cond(result))
+ log(msg + ": " + result)
+
+ result
+ }
/** Are we compiling for Java SE? */
// def forJVM: Boolean
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index f4039cf6d3..2019b92836 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -543,7 +543,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Conditions where we omit the prefix when printing a symbol, to avoid
* unpleasantries like Predef.String, $iw.$iw.Foo and <empty>.Bippy.
*/
- final def isOmittablePrefix = !settings.debug.value && (
+ final def isOmittablePrefix = /*!settings.debug.value &&*/ (
UnqualifiedOwners(skipPackageObject)
|| isEmptyPrefix
)
@@ -1191,9 +1191,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
var ph = phase
while (ph.prev.keepsTypeParams)
ph = ph.prev
-
- if (ph ne phase)
- debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph)
+ //
+ // if (ph ne phase)
+ // debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph)
ph
}
@@ -2119,7 +2119,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else ""
def defaultFlagMask =
- if (settings.debug.value) -1L
+ if (isAbstractType) ExplicitFlags
+ else if (settings.debug.value) -1L
else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
else ExplicitFlags
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 8e326c202a..b7b4212b93 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -871,7 +871,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
debuglog("Adding field: " + f.symbol.fullName)
val jfield = jclass.addNewField(
- javaFlags(f.symbol) | javaFieldFlags(f.symbol),
+ javaFieldFlags(f.symbol),
javaName(f.symbol),
javaType(f.symbol.tpe)
)
@@ -1915,16 +1915,30 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val privateFlag =
sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner))
- // This does not check .isFinal (which checks flags for the FINAL flag),
- // instead checking rawflags for that flag so as to exclude symbols which
- // received lateFINAL. These symbols are eligible for inlining, but to
- // avoid breaking proxy software which depends on subclassing, we avoid
- // insisting on their finality in the bytecode.
+ // Final: the only fields which can receive ACC_FINAL are eager vals.
+ // Neither vars nor lazy vals can, because:
+ //
+ // Source: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3
+ // "Another problem is that the specification allows aggressive
+ // optimization of final fields. Within a thread, it is permissible to
+ // reorder reads of a final field with those modifications of a final
+ // field that do not take place in the constructor."
+ //
+ // A var or lazy val which is marked final still has meaning to the
+ // scala compiler. The word final is heavily overloaded unfortunately;
+ // for us it means "not overridable". At present you can't override
+ // vars regardless; this may change.
+ //
+ // The logic does not check .isFinal (which checks flags for the FINAL flag,
+ // and includes symbols marked lateFINAL) instead inspecting rawflags so
+ // we can exclude lateFINAL. Such symbols are eligible for inlining, but to
+ // avoid breaking proxy software which depends on subclassing, we do not
+ // emit ACC_FINAL.
val finalFlag = (
((sym.rawflags & (Flags.FINAL | Flags.MODULE)) != 0)
&& !sym.enclClass.isInterface
&& !sym.isClassConstructor
- && !sym.isMutable // fix for SI-3569, it is too broad?
+ && !sym.isMutable // lazy vals and vars both
)
mkFlags(
@@ -1939,13 +1953,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (sym.hasFlag(Flags.SYNCHRONIZED)) JAVA_ACC_SYNCHRONIZED else 0
)
}
- def javaFieldFlags(sym: Symbol) = {
- mkFlags(
+ def javaFieldFlags(sym: Symbol) = (
+ javaFlags(sym) | mkFlags(
if (sym hasAnnotation TransientAttr) ACC_TRANSIENT else 0,
if (sym hasAnnotation VolatileAttr) ACC_VOLATILE else 0,
if (sym.isMutable) 0 else ACC_FINAL
)
- }
+ )
def isTopLevelModule(sym: Symbol): Boolean =
afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index fdde8f9990..14b3bcc8ce 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -31,7 +31,7 @@ trait ScalaSettings extends AbsScalaSettings
protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".")
/** Enabled under -Xexperimental. */
- protected def experimentalSettings = List[BooleanSetting](YmethodInfer, overrideObjects)
+ protected def experimentalSettings = List[BooleanSetting](YmethodInfer, overrideObjects, overrideVars)
/** Enabled under -Xfuture. */
protected def futureSettings = List[BooleanSetting]()
@@ -117,6 +117,7 @@ trait ScalaSettings extends AbsScalaSettings
* -Y "Private" settings
*/
val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.")
+ val overrideVars = BooleanSetting ("-Yoverride-vars", "Allow vars to be overridden.")
val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.")
val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 7b0f5254b6..185cf4f533 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -318,7 +318,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else specializedTypeVars(sym).intersect(env.keySet)
)
val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod)
- debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
+ // debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
specializedName(sym.name, methparams map env, others map env)
}
@@ -518,7 +518,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// better evaluate it before creating the new class symbol
val clazzName = specializedName(clazz, env0).toTypeName
val bytecodeClazz = clazz.owner.info.decl(clazzName)
- debuglog("Specializing " + clazz + " found " + bytecodeClazz + " already there")
+ // debuglog("Specializing " + clazz + ", but found " + bytecodeClazz + " already there")
bytecodeClazz.info
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
@@ -574,7 +574,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
parents = parents.head.parents.head :: parents
val extraSpecializedMixins = specializedParents(clazz.info.parents map applyContext)
if (extraSpecializedMixins.nonEmpty)
- debuglog("specializeClass on " + clazz + " founds extra specialized mixins: " + extraSpecializedMixins.mkString(", "))
+ debuglog("extra specialized mixins for %s: %s".format(clazz.name.decode, extraSpecializedMixins.mkString(", ")))
// If the class being specialized has a self-type, the self type may
// require specialization. First exclude classes whose self types have
// the same type constructor as the class itself, since they will
@@ -652,7 +652,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val NormalizedMember(original) = info(m)
if (nonConflicting(env ++ typeEnv(m))) {
if (info(m).degenerate) {
- debuglog("degenerate normalized member " + m + " info(m): " + info(m))
+ debuglog("degenerate normalized member " + m.defString)
val specMember = enterMember(cloneInSpecializedClass(m, _ & ~DEFERRED))
info(specMember) = Implementation(original)
@@ -660,7 +660,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
else debuglog({
val om = forwardToOverload(m)
- "normalizedMember " + m + " om: " + om + " typeEnv(om): " + typeEnv(om)
+ "normalizedMember " + m + " om: " + om + " " + pp(typeEnv(om))
})
}
else
@@ -668,7 +668,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
else if (m.isDeferred) { // abstract methods
val specMember = enterMember(cloneInSpecializedClass(m, _ | DEFERRED))
- debuglog("deferred " + specMember.fullName + " remains abstract")
+ // debuglog("deferred " + specMember.fullName + " remains abstract")
info(specMember) = new Abstract(specMember)
// was: new Forward(specMember) {
@@ -698,20 +698,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
enterMember(specVal)
// create accessors
- debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
+ // debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
+
if (nme.isLocalName(m.name)) {
val specGetter = mkAccessor(specVal, nme.localToGetter(specVal.name)) setInfo MethodType(Nil, specVal.info)
val origGetter = overrideIn(sClass, m.getter(clazz))
info(origGetter) = Forward(specGetter)
enterMember(specGetter)
enterMember(origGetter)
- debuglog("created accessors: " + specGetter + " orig: " + origGetter)
+ debuglog("specialize accessor in %s: %s -> %s".format(sClass.name.decode, origGetter.name.decode, specGetter.name.decode))
clazz.caseFieldAccessors.find(_.name.startsWith(m.name)) foreach { cfa =>
val cfaGetter = overrideIn(sClass, cfa)
info(cfaGetter) = SpecializedAccessor(specVal)
enterMember(cfaGetter)
- debuglog("found case field accessor for " + m + " added override " + cfaGetter);
+ debuglog("override case field accessor %s -> %s".format(m.name.decode, cfaGetter.name.decode))
}
if (specVal.isVariable && m.setter(clazz) != NoSymbol) {
@@ -724,11 +725,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
enterMember(specSetter)
enterMember(origSetter)
}
- } else { // if there are no accessors, specialized methods will need to access this field in specialized subclasses
+ }
+ else { // if there are no accessors, specialized methods will need to access this field in specialized subclasses
m.resetFlag(PRIVATE)
specVal.resetFlag(PRIVATE)
+ debuglog("no accessors for %s/%s, specialized methods must access field in subclass".format(
+ m.name.decode, specVal.name.decode))
}
- } else if (m.isClass) {
+ }
+ else if (m.isClass) {
val specClass: Symbol = cloneInSpecializedClass(m, x => x)
typeEnv(specClass) = fullEnv
specClass.name = specializedName(specClass, fullEnv).toTypeName
@@ -787,10 +792,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* // etc.
*/
private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = {
- debuglog("normalizeMember: " + sym.fullName)
sym :: (
if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil
else {
+ // debuglog("normalizeMember: " + sym.fullNameAsName('.').decode)
var specializingOn = specializedParams(sym)
val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info)
@@ -810,7 +815,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val (keys, vals) = env.toList.unzip
specMember.name = specializedName(sym, env)
- debuglog("normalizing: " + sym + " to " + specMember + " with params " + tps)
+ // debuglog("%s normalizes to %s%s".format(sym, specMember,
+ // if (tps.isEmpty) "" else " with params " + tps.mkString(", ")))
typeEnv(specMember) = outerEnv ++ env
val tps1 = produceTypeParameters(tps, specMember, env)
@@ -820,11 +826,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val methodType = sym.info.resultType.instantiateTypeParams(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember)
specMember setInfo GenPolyType(tps1, methodType)
- debuglog("expanded member: " + sym + ": " + sym.info +
- " -> " + specMember +
- ": " + specMember.info +
- " env: " + env
- )
+ debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
info(specMember) = NormalizedMember(sym)
overloads(sym) ::= Overload(specMember, env)
specMember
@@ -833,6 +835,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
)
}
+ // concise printing of type env
+ private def pp(env: TypeEnv): String = {
+ env.toList.sortBy(_._1.name.toString) map {
+ case (k, v) =>
+ val vsym = v.typeSymbol
+ if (k == vsym) "" + k.name
+ else k.name + ":" + vsym.name
+
+ } mkString ("env(", ", ", ")")
+ }
+
/** Specialize member `m` w.r.t. to the outer environment and the type
* parameters of the innermost enclosing class.
*
@@ -841,37 +854,38 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Return a list of symbols that are specializations of 'sym', owned by 'owner'.
*/
private def specializeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv, tps: List[Symbol]): List[Symbol] = {
- def specializeOn(tparams: List[Symbol]): List[Symbol] =
- for (spec0 <- specializations(tparams)) yield {
- val spec = mapAnyRefsInOrigCls(spec0, owner)
- if (sym.isPrivate/* || sym.isProtected*/) {
- //sym.privateWithin = sym.enclosingPackage
- sym.resetFlag(PRIVATE).setFlag(PROTECTED)
- debuglog("-->d SETTING PRIVATE WITHIN TO " + sym.enclosingPackage + " for " + sym)
- }
+ def specializeOn(tparams: List[Symbol]): List[Symbol] = specializations(tparams) map { spec0 =>
+ val spec = mapAnyRefsInOrigCls(spec0, owner)
+ if (sym.isPrivate) {
+ sym.resetFlag(PRIVATE).setFlag(PROTECTED)
+ debuglog("Set %s to private[%s]".format(sym, sym.enclosingPackage))
+ }
- val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
- typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
- wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
+ val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
+ typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
+ wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
- debuglog("sym " + specMember + " was specialized for type vars " + wasSpecializedForTypeVars(specMember))
- debuglog("added specialized overload: %s in env: %s".format(specMember, typeEnv(specMember)))
+ val wasSpec = wasSpecializedForTypeVars(specMember)
+ if (wasSpec.nonEmpty)
+ debuglog("specialized overload for %s in %s".format(specMember, pp(typeEnv(specMember))))
- overloads(sym) ::= Overload(specMember, spec)
- specMember
- }
+ overloads(sym) ::= Overload(specMember, spec)
+ info(specMember) = SpecialOverload(sym, typeEnv(specMember))
+
+ specMember
+ }
if (sym.isMethod) {
- debuglog("specializeMember %s with tps: %s stvars(sym): %s".format(sym, tps, specializedTypeVars(sym)))
+ val stvars = specializedTypeVars(sym)
+ if (stvars.nonEmpty)
+ debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", ")))
val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps
- val tps2 = tps1 intersect specializedTypeVars(sym).toList
+ val tps2 = tps1 filter stvars
if (!sym.isDeferred)
addConcreteSpecMethod(sym)
- val ms = specializeOn(tps2)
- ms foreach (m => info(m) = SpecialOverload(sym, typeEnv(m)))
- ms
+ specializeOn(tps2)
}
else Nil
}
@@ -894,7 +908,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*
* this method will return List('apply$mcII$sp')
*/
- private def specialOverrides(clazz: Symbol): List[Symbol] = {
+ private def specialOverrides(clazz: Symbol) = logResultIf[List[Symbol]]("specialOverrides(" + clazz + ")", _.nonEmpty) {
/** Return the overridden symbol in syms that needs a specialized overriding symbol,
* together with its specialization environment. The overridden symbol may not be
* the closest to 'overriding', in a given hierarchy.
@@ -917,24 +931,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
if (!overriding.isParamAccessor) {
for (overridden <- overriding.allOverriddenSymbols) {
- debuglog(
- "Overridden: " + overridden.fullName +
- ": " + overridden.info +
- "\n by " + overriding.fullName +
- ": " + overriding.info
- )
val stvars = specializedTypeVars(overridden.info)
if (stvars.nonEmpty) {
- debuglog("\t\tspecializedTVars: " + stvars)
+ debuglog("specialized override of %s by %s%s".format(overridden.fullLocationString, overriding.fullLocationString,
+ if (stvars.isEmpty) "" else stvars.map(_.name).mkString("(", ", ", ")")))
+
if (currentRun compiles overriding)
checkOverriddenTParams(overridden)
val env = unify(overridden.info, overriding.info, emptyEnv, false)
def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
- debuglog("\t\tenv: " + env + "isValid: " + TypeEnv.isValid(env, overridden) + "found: " + atNext)
- if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol)
+ if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) {
+ debuglog(" " + pp(env) + " found " + atNext)
return (overridden, env)
+ }
}
}
}
@@ -945,7 +956,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (NoSymbol, _) => None
case (overridden, env) =>
val om = specializedOverload(clazz, overridden, env)
- debuglog("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info))
+ debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info))
typeEnv(om) = env
addConcreteSpecMethod(overriding)
info(om) = (
@@ -993,7 +1004,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) =>
- debuglog("Unify - basic case: " + tp1 + ", " + tp2)
+ debuglog("Unify " + tp1 + ", " + tp2)
if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
env + ((sym1, tp2))
else if (isSpecializedAnyRefSubtype(tp2, sym1))
@@ -1003,19 +1014,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else
env
case (TypeRef(_, sym1, args1), TypeRef(_, sym2, args2)) =>
- debuglog("Unify TypeRefs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - ")
+ if (args1.nonEmpty || args2.nonEmpty)
+ debuglog("Unify types " + tp1 + " and " + tp2)
+
if (strict && args1.length != args2.length) unifyError(tp1, tp2)
val e = unify(args1, args2, env, strict)
- debuglog("unified to: " + e)
+ if (e.nonEmpty) debuglog("unified to: " + e)
e
case (TypeRef(_, sym1, _), _) if sym1.isTypeParameterOrSkolem =>
env
case (MethodType(params1, res1), MethodType(params2, res2)) =>
if (strict && params1.length != params2.length) unifyError(tp1, tp2)
- debuglog("Unify MethodTypes: " + tp1 + " and " + tp2)
+ debuglog("Unify methods " + tp1 + " and " + tp2)
unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict)
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
- debuglog("Unify PolyTypes: " + tp1 + " and " + tp2)
+ debuglog("Unify polytypes " + tp1 + " and " + tp2)
if (strict && tparams1.length != tparams2.length)
unifyError(tp1, tp2)
else
@@ -1123,11 +1136,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (tparams.isEmpty)
afterSpecialize(parents map (_.typeSymbol.info))
- val parents1 = parents map specializedType
- debuglog("transformInfo %s %s with parents1 %s ph: %s".format(
- if (tparams.nonEmpty) " (poly)" else "",
- clazz, parents1, phase)
- )
+ val parents1 = parents mapConserve specializedType
+ if (parents ne parents1) {
+ debuglog("specialization transforms %s%s parents to %s".format(
+ if (tparams.nonEmpty) "(poly) " else "", clazz, parents1)
+ )
+ }
val newScope = newScopeWith(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz): _*)
// If tparams.isEmpty, this is just the ClassInfoType.
GenPolyType(tparams, ClassInfoType(parents1, newScope, clazz))
@@ -1253,7 +1267,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
override def traverse(tree: Tree) = tree match {
case DefDef(_, _, _, vparams :: Nil, _, rhs) =>
if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) {
- debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
+ // debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
body(tree.symbol) = rhs
// body(tree.symbol) = tree // whole method
parameters(tree.symbol) = vparams.map(_.symbol)
@@ -1559,7 +1573,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val env = typeEnv(symbol)
val boundTvars = env.keySet
val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam)))
- debuglog("substituting " + origtparams + " for " + symbol.typeParams)
+ if (origtparams.nonEmpty || symbol.typeParams.nonEmpty)
+ debuglog("substituting " + origtparams + " for " + symbol.typeParams)
// skolemize type parameters
val oldtparams = tparams map (_.symbol)
@@ -1656,7 +1671,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
buf +=
ClassDef(specCls, atPos(impl.pos)(Template(parents, emptyValDef, List()))
.setSymbol(specCls.newLocalDummy(sym1.pos))) setPos tree.pos
- debuglog("created synthetic class: " + specCls + " of " + sym1 + " in env: " + env)
+ debuglog("created synthetic class: " + specCls + " of " + sym1 + " in " + pp(env))
}
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 6b27c27652..8604366bf2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -315,9 +315,10 @@ trait Namers extends MethodSynthesis {
case DefDef(_, _, _, _, _, _) => owner.newMethod(name.toTermName, pos, flags)
case ClassDef(_, _, _, _) => owner.newClassSymbol(name.toTypeName, pos, flags)
case ModuleDef(_, _, _) => owner.newModule(name, pos, flags)
- case ValDef(_, _, _, _) if isParameter => owner.newValueParameter(name, pos, flags)
case PackageDef(pid, _) => createPackageSymbol(pos, pid)
- case ValDef(_, _, _, _) => owner.newValue(name, pos, flags)
+ case ValDef(_, _, _, _) =>
+ if (isParameter) owner.newValueParameter(name, pos, flags)
+ else owner.newValue(name, pos, flags)
}
}
private def createFieldSymbol(tree: ValDef): TermSymbol =
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 013a74da7e..9177aca656 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -394,9 +394,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("needs `override' modifier")
} else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) {
overrideError("needs `abstract override' modifiers")
- } else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) {
- overrideError("cannot override a mutable variable")
- } else if (member.isAnyOverride &&
+ }
+ else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) {
+ // !?! this is not covered by the spec. We need to resolve this either by changing the spec or removing the test here.
+ // !!! is there a !?! convention? I'm !!!ing this to make sure it turns up on my searches.
+ if (!settings.overrideVars.value)
+ overrideError("cannot override a mutable variable")
+ }
+ else if (member.isAnyOverride &&
!(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) &&
!member.isDeferred && !other.isDeferred &&
intersectionIsEmpty(member.extendedOverriddenSymbols, other.extendedOverriddenSymbols)) {
@@ -1248,9 +1253,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
List(tree1)
}
- case Import(_, _) => Nil
+ case Import(_, _) => Nil
case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) => Nil
- case _ => List(transform(tree))
+ case _ => List(transform(tree))
}
/* Check whether argument types conform to bounds of type parameters */
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 4248b6f024..94733369a8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -259,7 +259,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case sel @ Select(Super(_, mix), name) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
- unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
+ if (!settings.overrideVars.value)
+ unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
}
else if (isDisallowed(sym)) {
unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 870c179b2d..1b75c10113 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -58,7 +58,7 @@ import java.io._
* @author Martin Odersky and others
* @version 2.8
* @since 1.0
- * @see [["http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists" "Scala's Collection Library overview"]]
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists "Scala's Collection Library overview"]]
* section on `Lists` for more information.
*
* @define coll list
diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala
index 8fad131009..b70df05c55 100644
--- a/src/library/scala/collection/mutable/Stack.scala
+++ b/src/library/scala/collection/mutable/Stack.scala
@@ -44,7 +44,7 @@ object Stack extends SeqFactory[Stack] {
* @author Martin Odersky
* @version 2.8
* @since 1
- * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks"Scala's Collection Library overview"]]
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks "Scala's Collection Library overview"]]
* section on `Stacks` for more information.
* @define Coll Stack
* @define coll stack
diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
index 49b00bebdb..e630a9dbed 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
@@ -36,7 +36,9 @@ import collection.parallel.Task
*
* @author Aleksandar Prokopec
* @since 2.9
- *
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tries for more information.
+ *
* @define Coll immutable.ParHashMap
* @define coll immutable parallel hash map
*/
diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
index 11d92a27c9..084637c5dc 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
@@ -35,6 +35,8 @@ import collection.parallel.Task
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tries for more information.
*
* @define Coll immutable.ParHashSet
* @define coll immutable parallel hash set
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index 9cac433460..277fd5fdd3 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -25,6 +25,8 @@ import scala.collection.Iterator
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_range Scala's Parallel Collections Library overview]]
+ * section on `ParRange` for more information.
*
* @define Coll immutable.ParRange
* @define coll immutable parallel range
diff --git a/src/library/scala/collection/parallel/immutable/ParVector.scala b/src/library/scala/collection/parallel/immutable/ParVector.scala
index 5d9c431bc1..8baa84b77c 100644
--- a/src/library/scala/collection/parallel/immutable/ParVector.scala
+++ b/src/library/scala/collection/parallel/immutable/ParVector.scala
@@ -34,6 +34,8 @@ import immutable.VectorIterator
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_vector Scala's Parallel Collections Library overview]]
+ * section on `ParVector` for more information.
*
* @define Coll immutable.ParVector
* @define coll immutable parallel vector
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index c33495bd39..8cc0b95997 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -44,10 +44,14 @@ import scala.collection.GenTraversableOnce
*
* @tparam T type of the elements in the array
*
+ * @author Aleksandar Prokopec
+ * @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_array Scala's Parallel Collections Library overview]]
+ * section on `ParArray` for more information.
+ *
* @define Coll ParArray
* @define coll parallel array
*
- * @author Aleksandar Prokopec
*/
@SerialVersionUID(1L)
class ParArray[T] private[mutable] (val arrayseq: ArraySeq[T])
diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
index 6ce6c45460..23b23d55a1 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
@@ -32,6 +32,8 @@ import collection.parallel.Task
* @define coll parallel hash map
*
* @author Aleksandar Prokopec
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tables Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tables for more information.
*/
@SerialVersionUID(1L)
class ParHashMap[K, V] private[collection] (contents: HashTable.Contents[K, DefaultEntry[K, V]])
diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
index e0a2ab03df..4e9a38c13f 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
@@ -29,6 +29,8 @@ import collection.parallel.Task
* @define coll parallel hash set
*
* @author Aleksandar Prokopec
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tables Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tables for more information.
*/
@SerialVersionUID(1L)
class ParHashSet[T] private[collection] (contents: FlatHashTable.Contents[T])
diff --git a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
index fa19990b91..359c35f1dd 100644
--- a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
@@ -33,6 +33,8 @@ import scala.collection.concurrent.TrieMapIterator
*
* @author Aleksandar Prokopec
* @since 2.10
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_concurrent_tries Scala's Parallel Collections Library overview]]
+ * section on `ParTrieMap` for more information.
*/
final class ParTrieMap[K, V] private[collection] (private val ctrie: TrieMap[K, V])
extends ParMap[K, V]
diff --git a/test/files/run/finalvar.check b/test/files/run/finalvar.check
new file mode 100644
index 0000000000..2496293972
--- /dev/null
+++ b/test/files/run/finalvar.check
@@ -0,0 +1,6 @@
+(2,2,2,2,1)
+(2,2,2,2)
+(2,2,2,2,1001)
+(2,2,2,2)
+2
+10
diff --git a/test/files/run/finalvar.flags b/test/files/run/finalvar.flags
new file mode 100644
index 0000000000..aee3039bec
--- /dev/null
+++ b/test/files/run/finalvar.flags
@@ -0,0 +1 @@
+-Yoverride-vars -Yinline \ No newline at end of file
diff --git a/test/files/run/finalvar.scala b/test/files/run/finalvar.scala
new file mode 100644
index 0000000000..010813e520
--- /dev/null
+++ b/test/files/run/finalvar.scala
@@ -0,0 +1,37 @@
+object Final {
+ class X(final var x: Int) { }
+ def f = new X(0).x += 1
+}
+
+class A {
+ var x = 1
+ def y0 = x
+ def y1 = this.x
+ def y2 = (this: A).x
+}
+
+class B extends A {
+ override def x = 2
+ def z = super.x
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ Final.f
+ val a = new B
+ println((a.x, a.y0, a.y1, a.y2, a.z))
+ val a0: A = a
+ println((a0.x, a0.y0, a0.y1, a0.y2))
+ a.x = 1001
+ println((a.x, a.y0, a.y1, a.y2, a.z))
+ println((a0.x, a0.y0, a0.y1, a0.y2))
+
+ val d = new D
+ println(d.w)
+ d.ten
+ println(d.w)
+ }
+}
+
+class C { var w = 1 ; def ten = this.w = 10 }
+class D extends C { override var w = 2 } \ No newline at end of file
diff --git a/test/pending/pos/t1476.scala b/test/pending/pos/t1476.scala
new file mode 100644
index 0000000000..1f8e95c28f
--- /dev/null
+++ b/test/pending/pos/t1476.scala
@@ -0,0 +1,23 @@
+abstract class Module {
+ def moduleDemands(): List[Module]
+}
+
+object Test {
+ new Module { owner: Module =>
+ def moduleDemands() = Nil
+
+ val a = new Module { def moduleDemands(): List[Module] = Nil }
+ val b = new Module { def moduleDemands(): List[Module] = owner :: c :: Nil }
+ val c = new Module { def moduleDemands(): List[Module] = owner :: a :: Nil }
+ }
+}
+
+object Test2 {
+ new Module { owner =>
+ def moduleDemands() = Nil
+
+ val a = new Module { def moduleDemands(): List[Module] = Nil }
+ val b = new Module { def moduleDemands(): List[Module] = owner :: c :: Nil }
+ val c = new Module { def moduleDemands(): List[Module] = owner :: a :: Nil }
+ }
+}
diff --git a/test/pending/pos/t5626.scala b/test/pending/pos/t5626.scala
new file mode 100644
index 0000000000..7ab3881827
--- /dev/null
+++ b/test/pending/pos/t5626.scala
@@ -0,0 +1,12 @@
+object Test {
+ val blob0 = new {
+ case class Foo(i : Int)
+ }
+ val foo0 = blob0.Foo(22)
+
+ val blob1 = new {
+ class Foo(i: Int)
+ object Foo { def apply(i: Int): Foo = new Foo(i) }
+ }
+ val foo1 = blob1.Foo(22)
+}
diff --git a/test/pending/run/t5629.check b/test/pending/run/t5629.check
new file mode 100644
index 0000000000..6a2d630f4e
--- /dev/null
+++ b/test/pending/run/t5629.check
@@ -0,0 +1,2 @@
+int child got: 33
+any child got: 33
diff --git a/test/pending/run/t5629.scala b/test/pending/run/t5629.scala
new file mode 100644
index 0000000000..28e74a1c94
--- /dev/null
+++ b/test/pending/run/t5629.scala
@@ -0,0 +1,25 @@
+import scala.{specialized => spec}
+
+trait GrandParent[@spec(Int) -A] {
+ def foo(a:A): Unit
+ def bar[B <: A](b:B): Unit = println("grandparent got: %s" format b)
+}
+
+trait Parent[@spec(Int) -A] extends GrandParent[A] {
+ def foo(a:A) = bar(a)
+}
+
+class IntChild extends Parent[Int] {
+ override def bar[B <: Int](b:B): Unit = println("int child got: %s" format b)
+}
+
+class AnyChild extends Parent[Any] {
+ override def bar[B <: Any](b:B): Unit = println("any child got: %s" format b)
+}
+
+object Test {
+ def main(args:Array[String]) {
+ new IntChild().foo(33)
+ new AnyChild().foo(33)
+ }
+}