diff options
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) + } +} |