diff options
author | Paul Phillips <paulp@improving.org> | 2012-07-11 11:59:33 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-07-11 11:59:33 -0700 |
commit | 30041d29545fc0596be6192882747c48f9b821e3 (patch) | |
tree | c01b82aec236c29ed69dc0add4e00c9a7c99b7ff | |
parent | a9b85dbaad568b5c709a5eb6ab23907cdf4ee29e (diff) | |
parent | 3d0099dbc990ab914de5b9deb5087d9d3fb6220c (diff) | |
download | scala-30041d29545fc0596be6192882747c48f9b821e3.tar.gz scala-30041d29545fc0596be6192882747c48f9b821e3.tar.bz2 scala-30041d29545fc0596be6192882747c48f9b821e3.zip |
Merge branch '2.10.x' into topic/pickledflags
Conflicts:
src/reflect/scala/reflect/internal/Flags.scala
68 files changed, 675 insertions, 194 deletions
diff --git a/lib/ant/ant-contrib.jar.desired.sha1 b/lib/ant/ant-contrib.jar.desired.sha1 index 56745657c5..65bcd122bf 100644 --- a/lib/ant/ant-contrib.jar.desired.sha1 +++ b/lib/ant/ant-contrib.jar.desired.sha1 @@ -1 +1 @@ -943cd5c8802b2a3a64a010efb86ec19bac142e40 ?ant-contrib.jar +943cd5c8802b2a3a64a010efb86ec19bac142e40 *ant-contrib.jar diff --git a/lib/ant/ant-dotnet-1.0.jar.desired.sha1 b/lib/ant/ant-dotnet-1.0.jar.desired.sha1 index 1f1dc9b8c1..d8b6a1ca85 100644 --- a/lib/ant/ant-dotnet-1.0.jar.desired.sha1 +++ b/lib/ant/ant-dotnet-1.0.jar.desired.sha1 @@ -1 +1 @@ -3fc1e35ca8c991fc3488548f7a276bd9053c179d ?ant-dotnet-1.0.jar +3fc1e35ca8c991fc3488548f7a276bd9053c179d *ant-dotnet-1.0.jar diff --git a/lib/ant/ant.jar.desired.sha1 b/lib/ant/ant.jar.desired.sha1 index 852b3397cb..bcb610d6de 100644 --- a/lib/ant/ant.jar.desired.sha1 +++ b/lib/ant/ant.jar.desired.sha1 @@ -1 +1 @@ -7b456ca6b93900f96e58cc8371f03d90a9c1c8d1 ?ant.jar +7b456ca6b93900f96e58cc8371f03d90a9c1c8d1 *ant.jar diff --git a/lib/ant/maven-ant-tasks-2.1.1.jar.desired.sha1 b/lib/ant/maven-ant-tasks-2.1.1.jar.desired.sha1 index 06dcb1e312..53f87c3461 100644 --- a/lib/ant/maven-ant-tasks-2.1.1.jar.desired.sha1 +++ b/lib/ant/maven-ant-tasks-2.1.1.jar.desired.sha1 @@ -1 +1 @@ -7e50e3e227d834695f1e0bf018a7326e06ee4c86 ?maven-ant-tasks-2.1.1.jar +7e50e3e227d834695f1e0bf018a7326e06ee4c86 *maven-ant-tasks-2.1.1.jar diff --git a/lib/ant/vizant.jar.desired.sha1 b/lib/ant/vizant.jar.desired.sha1 index 00ff17d159..998da4643a 100644 --- a/lib/ant/vizant.jar.desired.sha1 +++ b/lib/ant/vizant.jar.desired.sha1 @@ -1 +1 @@ -2c61d6e9a912b3253194d5d6d3e1db7e2545ac4b ?vizant.jar +2c61d6e9a912b3253194d5d6d3e1db7e2545ac4b *vizant.jar diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1 index d24a5d01fc..6f3ccc77bd 100644 --- a/lib/fjbg.jar.desired.sha1 +++ b/lib/fjbg.jar.desired.sha1 @@ -1 +1 @@ -c3f9b576c91cb9761932ad936ccc4a71f33d2ef2 ?fjbg.jar +8acc87f222210b4a5eb2675477602fc1759e7684 *fjbg.jar diff --git a/lib/forkjoin.jar.desired.sha1 b/lib/forkjoin.jar.desired.sha1 index d31539daf4..8b24962e2c 100644 --- a/lib/forkjoin.jar.desired.sha1 +++ b/lib/forkjoin.jar.desired.sha1 @@ -1 +1 @@ -b5baf94dff8d3ca991d44a59add7bcbf6640379b ?forkjoin.jar +f93a2525b5616d3a4bee7848fabbb2856b56f653 *forkjoin.jar diff --git a/lib/jline.jar.desired.sha1 b/lib/jline.jar.desired.sha1 index 8acb0c9b14..b0426130ac 100644 --- a/lib/jline.jar.desired.sha1 +++ b/lib/jline.jar.desired.sha1 @@ -1 +1 @@ -a5261e70728c1847639e2b47d953441d0b217bcb ?jline.jar +a5261e70728c1847639e2b47d953441d0b217bcb *jline.jar diff --git a/lib/msil.jar.desired.sha1 b/lib/msil.jar.desired.sha1 index 2c2fe79dda..9396b273ab 100644 --- a/lib/msil.jar.desired.sha1 +++ b/lib/msil.jar.desired.sha1 @@ -1 +1 @@ -d48cb950ceded82a5e0ffae8ef2c68d0923ed00c ?msil.jar +d48cb950ceded82a5e0ffae8ef2c68d0923ed00c *msil.jar diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index 9a47d9f730..b4404c3d24 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -554bcc4a543360c8dc48fde91124dc57319d3460 ?scala-compiler.jar +dacc6e38cdd2eabbf2e4780061c3b4c9e125274d *scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index 1ec21bc6ee..4711fc583e 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -7db4c7523f0e268ce58de2ab4ae6a3dd0e903f43 ?scala-library-src.jar +0772f79076f74e298e7bf77ad4dfa464c50efe61 *scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index ec73b5f7b8..3f92447c1a 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -071d32b24daaeaf961675f248758fedd31a806ed ?scala-library.jar +4edcb1b7030e74259cd906e9230d45a3fffc0444 *scala-library.jar diff --git a/lib/scala-reflect.jar.desired.sha1 b/lib/scala-reflect.jar.desired.sha1 index 4be2e84aef..1f8440cd4a 100644 --- a/lib/scala-reflect.jar.desired.sha1 +++ b/lib/scala-reflect.jar.desired.sha1 @@ -1 +1 @@ -b6e2bbbc1707104119adcb09aeb666690419c424 ?scala-reflect.jar +1187b9c68ca80f951826b1a9b374e8646d9c9a71 *scala-reflect.jar diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index ac2780f53e..324f0a4b65 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -295,6 +295,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
+ if (sym.isHidden) ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
if (sym.isVarargsMethod) ACC_VARARGS else 0,
if (sym.hasFlag(Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0
@@ -849,7 +850,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // without it. This is particularly bad because the availability of
// generic information could disappear as a consequence of a seemingly
// unrelated change.
- sym.isSynthetic
+ sym.isHidden
|| sym.isLiftedMethod
|| sym.isBridge
|| (sym.ownerChain exists (_.isImplClass))
@@ -2191,9 +2192,15 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val st = pending.getOrElseUpdate(lv, mutable.Stack.empty[Label])
st.push(start)
}
- def popScope(lv: Local, end: Label) {
- val start = pending(lv).pop()
- seen ::= LocVarEntry(lv, start, end)
+ def popScope(lv: Local, end: Label, iPos: Position) {
+ pending.get(lv) match {
+ case Some(st) if st.nonEmpty =>
+ val start = st.pop()
+ seen ::= LocVarEntry(lv, start, end)
+ case _ =>
+ // TODO SI-6049
+ getCurrentCUnit().warning(iPos, "Visited SCOPE_EXIT before visiting corresponding SCOPE_ENTER. SI-6049")
+ }
}
def getMerged(): collection.Map[Local, List[Interval]] = {
@@ -2406,7 +2413,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // similarly, these labels aren't tracked in the `labels` map.
val end = new asm.Label
jmethod.visitLabel(end)
- scoping.popScope(lv, end)
+ scoping.popScope(lv, end, instr.pos)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 21260d399c..9661ae6b3e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -727,7 +727,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // without it. This is particularly bad because the availability of // generic information could disappear as a consequence of a seemingly // unrelated change. - sym.isSynthetic + sym.isHidden || sym.isLiftedMethod || sym.isBridge || (sym.ownerChain exists (_.isImplClass)) @@ -1972,6 +1972,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0, if (sym.isStaticMember) ACC_STATIC else 0, if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, + if (sym.isHidden) ACC_SYNTHETIC else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(Flags.SYNCHRONIZED)) JAVA_ACC_SYNCHRONIZED else 0 diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala index f622f11ffd..afb8985700 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala @@ -82,13 +82,17 @@ abstract class InteractiveTest /** Test's entry point */ def main(args: Array[String]) { + try execute() + finally shutdown() + } + + protected def execute(): Unit = { loadSources() - runTests() - shutdown() + runDefaultTests() } /** Load all sources before executing the test. */ - private def loadSources() { + protected def loadSources() { // ask the presentation compiler to track all sources. We do // not wait for the file to be entirely typed because we do want // to exercise the presentation compiler on scoped type requests. @@ -100,7 +104,7 @@ abstract class InteractiveTest } /** Run all defined `PresentationCompilerTestDef` */ - protected def runTests() { + protected def runDefaultTests() { //TODO: integrate random tests!, i.e.: if (runRandomTests) randomTests(20, sourceFiles) testActions.foreach(_.runTest()) } @@ -109,7 +113,7 @@ abstract class InteractiveTest private def randomTests(n: Int, files: Array[SourceFile]) { val tester = new Tester(n, files, settings) { override val compiler = self.compiler - override val reporter = compilerReporter + override val reporter = new reporters.StoreReporter } tester.run() } diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala index 36671555d1..4d85ab9d88 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala @@ -4,10 +4,8 @@ package tests import java.io.File.pathSeparatorChar import java.io.File.separatorChar - import scala.tools.nsc.interactive.tests.core.PresentationCompilerInstance -import scala.tools.nsc.io.File - +import scala.tools.nsc.io.{File,Path} import core.Reporter import core.TestSettings @@ -46,6 +44,11 @@ trait InteractiveTestSettings extends TestSettings with PresentationCompilerInst println("error processing arguments (unprocessed: %s)".format(rest)) case _ => () } + + // Make the --sourcepath path provided in the .flags file (if any) relative to the test's base directory + if(settings.sourcepath.isSetByUser) + settings.sourcepath.value = (baseDir / Path(settings.sourcepath.value)).path + adjustPaths(settings.bootclasspath, settings.classpath, settings.javabootclasspath, settings.sourcepath) } diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala index 8ccb5aa075..5c1837b3bf 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala @@ -2,12 +2,15 @@ package scala.tools.nsc package interactive package tests.core -import reporters.StoreReporter +import reporters.{Reporter => CompilerReporter} +import scala.reflect.internal.util.Position /** Trait encapsulating the creation of a presentation compiler's instance.*/ -private[tests] trait PresentationCompilerInstance { +private[tests] trait PresentationCompilerInstance extends TestSettings { protected val settings = new Settings - protected val compilerReporter = new StoreReporter + protected val compilerReporter: CompilerReporter = new InteractiveReporter { + override def compiler = PresentationCompilerInstance.this.compiler + } protected lazy val compiler: Global = { prepareSettings(settings) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 65b0ff1e6d..e6499c05a6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -862,7 +862,7 @@ abstract class ClassfileParser { } else in.skip(attrLen) case tpnme.SyntheticATTR => - sym.setFlag(SYNTHETIC) + sym.setFlag(SYNTHETIC | HIDDEN) in.skip(attrLen) case tpnme.BridgeATTR => sym.setFlag(BRIDGE) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 1b8513373d..ab7bbc591b 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -92,7 +92,7 @@ abstract class ExplicitOuter extends InfoTransform else findOrElse(clazz.info.decls)(_.outerSource == clazz)(NoSymbol) } def newOuterAccessor(clazz: Symbol) = { - val accFlags = SYNTHETIC | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) + val accFlags = SYNTHETIC | HIDDEN | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags) val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType @@ -101,7 +101,7 @@ abstract class ExplicitOuter extends InfoTransform sym setInfo MethodType(Nil, restpe) } def newOuterField(clazz: Symbol) = { - val accFlags = SYNTHETIC | PARAMACCESSOR | ( if (clazz.isEffectivelyFinal) PrivateLocal else PROTECTED ) + val accFlags = SYNTHETIC | HIDDEN | PARAMACCESSOR | ( if (clazz.isEffectivelyFinal) PrivateLocal else PROTECTED ) val sym = clazz.newValue(nme.OUTER_LOCAL, clazz.pos, accFlags) sym setInfo clazz.outerClass.thisType diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 49f5fca19d..ba6c43f9d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -562,7 +562,9 @@ trait ContextErrors { // SelectFromTypeTree def TypeSelectionFromVolatileTypeError(tree: Tree, qual: Tree) = { - issueNormalTypeError(tree, "illegal type selection from volatile type "+qual.tpe) + val hiBound = qual.tpe.bounds.hi + val addendum = if (hiBound =:= qual.tpe) "" else s" (with upper bound ${hiBound})" + issueNormalTypeError(tree, s"illegal type selection from volatile type ${qual.tpe}${addendum}") setError(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 6428173577..9580cd5676 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -52,27 +52,6 @@ trait Namers extends MethodSynthesis { def newNamerFor(context: Context, tree: Tree): Namer = newNamer(context.makeNewScope(tree, tree.symbol)) - // In the typeCompleter (templateSig) of a case class (resp it's module), - // synthetic `copy` (reps `apply`, `unapply`) methods are added. To compute - // their signatures, the corresponding ClassDef is needed. - // During naming, for each case class module symbol, the corresponding ClassDef - // is stored in this map. The map is cleared lazily, i.e. when the new symbol - // is created with the same name, the old one (if present) is wiped out, or the - // entry is deleted when it is used and no longer needed. - private val classOfModuleClass = perRunCaches.newWeakMap[Symbol, WeakReference[ClassDef]]() - - // Default getters of constructors are added to the companion object in the - // typeCompleter of the constructor (methodSig). To compute the signature, - // we need the ClassDef. To create and enter the symbols into the companion - // object, we need the templateNamer of that module class. - // This map is extended during naming of classes, the Namer is added in when - // it's available, i.e. in the type completer (templateSig) of the module class. - private[typechecker] val classAndNamerOfModule = perRunCaches.newMap[Symbol, (ClassDef, Namer)]() - - def resetNamer() { - classAndNamerOfModule.clear() - } - abstract class Namer(val context: Context) extends MethodSynth with NamerContextErrors { thisNamer => import NamerErrorGen._ @@ -618,7 +597,7 @@ trait Namers extends MethodSynthesis { MaxParametersCaseClassError(tree) val m = ensureCompanionObject(tree, caseModuleDef) - classOfModuleClass(m.moduleClass) = new WeakReference(tree) + m.moduleClass.addAttachment(new ClassForCaseCompanionAttachment(tree)) } val hasDefault = impl.body exists { case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault) @@ -626,7 +605,7 @@ trait Namers extends MethodSynthesis { } if (hasDefault) { val m = ensureCompanionObject(tree) - classAndNamerOfModule(m) = (tree, null) + m.addAttachment(new ConstructorDefaultsAttachment(tree, null)) } val owner = tree.symbol.owner if (settings.lint.value && owner.isPackageObjectClass && !mods.isImplicit) { @@ -657,7 +636,8 @@ trait Namers extends MethodSynthesis { if (sym.isLazy) sym.lazyAccessor andAlso enterIfNotThere - defaultParametersOfMethod(sym) foreach { symRef => enterIfNotThere(symRef()) } + for (defAtt <- sym.attachments.get[DefaultsOfLocalMethodAttachment]) + defAtt.defaultGetters foreach enterIfNotThere } this.context } @@ -846,23 +826,20 @@ trait Namers extends MethodSynthesis { // add apply and unapply methods to companion objects of case classes, // unless they exist already; here, "clazz" is the module class if (clazz.isModuleClass) { - Namers.this.classOfModuleClass get clazz foreach { cdefRef => - val cdef = cdefRef() - if (cdef.mods.isCase) addApplyUnapply(cdef, templateNamer) - classOfModuleClass -= clazz + clazz.attachments.get[ClassForCaseCompanionAttachment] foreach { cma => + val cdef = cma.caseClass + assert(cdef.mods.isCase, "expected case class: "+ cdef) + addApplyUnapply(cdef, templateNamer) } } // add the copy method to case classes; this needs to be done here, not in SyntheticMethods, because // the namer phase must traverse this copy method to create default getters for its parameters. // here, clazz is the ClassSymbol of the case class (not the module). - // @check: this seems to work only if the type completer of the class runs before the one of the - // module class: the one from the module class removes the entry from classOfModuleClass (see above). if (clazz.isClass && !clazz.hasModuleFlag) { val modClass = companionSymbolOf(clazz, context).moduleClass - Namers.this.classOfModuleClass get modClass map { cdefRef => - val cdef = cdefRef() - + modClass.attachments.get[ClassForCaseCompanionAttachment] foreach { cma => + val cdef = cma.caseClass def hasCopy(decls: Scope) = (decls lookup nme.copy) != NoSymbol if (cdef.mods.isCase && !hasCopy(decls) && !parents.exists(p => hasCopy(p.typeSymbol.info.decls)) && @@ -874,9 +851,8 @@ trait Namers extends MethodSynthesis { // if default getters (for constructor defaults) need to be added to that module, here's the namer // to use. clazz is the ModuleClass. sourceModule works also for classes defined in methods. val module = clazz.sourceModule - classAndNamerOfModule get module foreach { - case (cdef, _) => - classAndNamerOfModule(module) = (cdef, templateNamer) + for (cda <- module.attachments.get[ConstructorDefaultsAttachment]) { + cda.companionModuleClassNamer = templateNamer } ClassInfoType(parents, decls, clazz) } @@ -1097,13 +1073,15 @@ trait Namers extends MethodSynthesis { val module = companionSymbolOf(clazz, context) module.initialize // call type completer (typedTemplate), adds the // module's templateNamer to classAndNamerOfModule - classAndNamerOfModule get module match { - case s @ Some((cdef, nmr)) if nmr != null => - moduleNamer = s - (cdef, nmr) + module.attachments.get[ConstructorDefaultsAttachment] match { + // by martin: the null case can happen in IDE; this is really an ugly hack on top of an ugly hack but it seems to work + // later by lukas: disabled when fixing SI-5975, i think it cannot happen anymore + case Some(cda) /*if cma.companionModuleClassNamer == null*/ => + val p = (cda.classWithDefault, cda.companionModuleClassNamer) + moduleNamer = Some(p) + p case _ => return // fix #3649 (prevent crash in erroneous source code) - // nmr == null can happen in IDE; this is really an ugly hack on top[ of an ugly hack but it seems to work } } deftParams = cdef.tparams map copyUntypedInvariant @@ -1141,11 +1119,14 @@ trait Namers extends MethodSynthesis { clazz.resetFlag(INTERFACE) // there's a concrete member now val default = parentNamer.enterSyntheticSym(defaultTree) if (forInteractive && default.owner.isTerm) { - // enter into map from method symbols to default arguments. - // if compiling the same local block several times (which can happen in interactive mode) - // we might otherwise not find the default symbol, because the second time it the - // method symbol will be re-entered in the scope but the default parameter will not. - defaultParametersOfMethod(meth) += new WeakReference(default) + // save the default getters as attachments in the method symbol. if compiling the + // same local block several times (which can happen in interactive mode) we might + // otherwise not find the default symbol, because the second time it the method + // symbol will be re-entered in the scope but the default parameter will not. + val att = meth.attachments.get[DefaultsOfLocalMethodAttachment] match { + case Some(att) => att.defaultGetters += default + case None => meth.addAttachment(new DefaultsOfLocalMethodAttachment(default)) + } } } else if (baseHasDefault) { // the parameter does not have a default itself, but the diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 61443faba0..a0c1342026 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -21,8 +21,19 @@ trait NamesDefaults { self: Analyzer => import definitions._ import NamesDefaultsErrorsGen._ - val defaultParametersOfMethod = - perRunCaches.newWeakMap[Symbol, Set[WeakReference[Symbol]]]() withDefaultValue Set() + // Default getters of constructors are added to the companion object in the + // typeCompleter of the constructor (methodSig). To compute the signature, + // we need the ClassDef. To create and enter the symbols into the companion + // object, we need the templateNamer of that module class. These two are stored + // as an attachment in the companion module symbol + class ConstructorDefaultsAttachment(val classWithDefault: ClassDef, var companionModuleClassNamer: Namer) + + // To attach the default getters of local (term-owned) methods to the method symbol. + // Used in Namer.enterExistingSym: it needs to re-enter the method symbol and also + // default getters, which could not be found otherwise. + class DefaultsOfLocalMethodAttachment(val defaultGetters: mutable.Set[Symbol]) { + def this(default: Symbol) = this(mutable.Set(default)) + } case class NamedApplyInfo( qual: Option[Tree], diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 53c2d16928..53843adea9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -8,7 +8,7 @@ package scala.tools.nsc package typechecker import symtab._ -import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC} +import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC, HIDDEN} import language.postfixOps import scala.tools.nsc.transform.TypingTransformers import scala.tools.nsc.transform.Transform @@ -949,7 +949,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix` // if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor? - val outer = expectedTp.typeSymbol.newMethod(vpmName.outer) setInfo expectedTp.prefix setFlag SYNTHETIC + val outer = expectedTp.typeSymbol.newMethod(vpmName.outer) setInfo expectedTp.prefix setFlag SYNTHETIC | HIDDEN (Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6aa93f9cec..b9fe269e43 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -47,7 +47,6 @@ trait Typers extends Modes with Adaptations with Tags { def resetTyper() { //println("resetTyper called") resetContexts() - resetNamer() resetImplicits() transformed.clear() } @@ -5114,7 +5113,7 @@ trait Typers extends Modes with Adaptations with Tags { case SelectFromTypeTree(qual, selector) => val qual1 = typedType(qual, mode) - if (qual1.tpe.isVolatile) TypeSelectionFromVolatileTypeError(tree, qual) + if (qual1.tpe.isVolatile) TypeSelectionFromVolatileTypeError(tree, qual1) else typedSelect(qual1, selector) case CompoundTypeTree(templ) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 1b89f3db44..ad936ac39d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -23,6 +23,14 @@ trait Unapplies extends ast.TreeDSL private val unapplyParamName = nme.x_0 + + // In the typeCompleter (templateSig) of a case class (resp it's module), + // synthetic `copy` (reps `apply`, `unapply`) methods are added. To compute + // their signatures, the corresponding ClassDef is needed. During naming (in + // `enterClassDef`), the case class ClassDef is added as an attachment to the + // moduleClass symbol of the companion module. + class ClassForCaseCompanionAttachment(val caseClass: ClassDef) + /** returns type list for return type of the extraction */ def unapplyTypeList(ufn: Symbol, ufntpe: Type) = { assert(ufn.isMethod, ufn) diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index 59160f87d0..8ea66979bc 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -15,8 +15,9 @@ trait FastTrack { import definitions._ import language.implicitConversions - private implicit def context2taggers(c0: MacroContext) : Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers - private implicit def context2contextreifiers(c0: MacroContext) : ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers + private implicit def context2taggers(c0: MacroContext): Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers + private implicit def context2contextreifiers(c0: MacroContext): ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers + private implicit def context2macroimplementations(c0: MacroContext): MacroImplementations { val c: c0.type } = new { val c: c0.type = c0 } with MacroImplementations implicit def fastTrackEntry2MacroRuntime(entry: FastTrackEntry): MacroRuntime = args => entry.run(args) type FastTrackExpander = PartialFunction[(MacroContext, Tree), Tree] @@ -42,6 +43,7 @@ trait FastTrack { ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } MacroContextReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExprForMacroContext(c.prefix.tree, expr) } ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree } + StringContext_f bindTo { case (c, Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args) } registry } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala new file mode 100644 index 0000000000..a5f7928f55 --- /dev/null +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala @@ -0,0 +1,147 @@ +package scala.tools.reflect + +import scala.reflect.makro.{ReificationError, UnexpectedReificationError} +import scala.reflect.makro.runtime.Context +import scala.collection.mutable.ListBuffer +import scala.collection.mutable.Stack + +abstract class MacroImplementations { + val c: Context + + import c.universe._ + + def macro_StringInterpolation_f(parts: List[Tree], args: List[Tree]): Tree = { + // the parts all have the same position information (as the expression is generated by the compiler) + // the args have correct position information + + // the following conditions can only be violated if invoked directly + if (parts.length != args.length + 1) { + if(parts.length == 0) + c.abort(c.prefix.tree.pos, "too few parts") + else if(args.length + 1 < parts.length) + c.abort(if(args.length==0) c.enclosingPosition else args.last.pos, + "too few arguments for interpolated string") + else + c.abort(args(parts.length-1).pos, + "too many arguments for interpolated string") + } + + val stringParts = parts map { + case Literal(Constant(s: String)) => s; + case _ => throw new IllegalArgumentException("argument parts must be a list of string literals") + } + + val pi = stringParts.iterator + val bldr = new java.lang.StringBuilder + val evals = ListBuffer[ValDef]() + val ids = ListBuffer[Ident]() + val argsStack = Stack(args : _*) + + def defval(value: Tree, tpe: Type): Unit = { + val freshName = newTermName(c.fresh("arg$")) + evals += ValDef(Modifiers(), freshName, TypeTree(tpe), value) + ids += Ident(freshName) + } + + def isFlag(ch: Char): Boolean = { + ch match { + case '-' | '#' | '+' | ' ' | '0' | ',' | '(' => true + case _ => false + } + } + + def checkType(arg: Tree, variants: Type*): Option[Type] = { + variants.find(arg.tpe <:< _).orElse( + variants.find(c.inferImplicitView(arg, arg.tpe, _) != EmptyTree).orElse( + Some(variants(0)) + ) + ) + } + + def conversionType(ch: Char, arg: Tree): Option[Type] = { + ch match { + case 'b' | 'B' => + if(arg.tpe <:< NullTpe) Some(NullTpe) else Some(BooleanTpe) + case 'h' | 'H' => + Some(AnyTpe) + case 's' | 'S' => + Some(AnyTpe) + case 'c' | 'C' => + checkType(arg, CharTpe, ByteTpe, ShortTpe, IntTpe) + case 'd' | 'o' | 'x' | 'X' => + checkType(arg, IntTpe, LongTpe, ByteTpe, ShortTpe, typeOf[BigInt]) + case 'e' | 'E' | 'g' | 'G' | 'f' | 'a' | 'A' => + checkType(arg, DoubleTpe, FloatTpe, typeOf[BigDecimal]) + case 't' | 'T' => + checkType(arg, LongTpe, typeOf[java.util.Calendar], typeOf[java.util.Date]) + case _ => None + } + } + + def copyString(first: Boolean): Unit = { + val str = StringContext.treatEscapes(pi.next()) + val strLen = str.length + val strIsEmpty = strLen == 0 + var start = 0 + var idx = 0 + + if (!first) { + val arg = argsStack.pop + if (strIsEmpty || (str charAt 0) != '%') { + bldr append "%s" + defval(arg, AnyTpe) + } else { + // PRE str is not empty and str(0) == '%' + // argument index parameter is not allowed, thus parse + // [flags][width][.precision]conversion + var pos = 1 + while(pos < strLen && isFlag(str charAt pos)) pos += 1 + while(pos < strLen && Character.isDigit(str charAt pos)) pos += 1 + if(pos < strLen && str.charAt(pos) == '.') { pos += 1 + while(pos < strLen && Character.isDigit(str charAt pos)) pos += 1 + } + if(pos < strLen) { + conversionType(str charAt pos, arg) match { + case Some(tpe) => defval(arg, tpe) + case None => c.error(arg.pos, "illegal conversion character") + } + } else { + // TODO: place error message on conversion string + c.error(arg.pos, "wrong conversion string") + } + } + idx = 1 + } + if (!strIsEmpty) { + val len = str.length + while (idx < len) { + if (str(idx) == '%') { + bldr append (str substring (start, idx)) append "%%" + start = idx + 1 + } + idx += 1 + } + bldr append (str substring (start, idx)) + } + } + + copyString(first = true) + while (pi.hasNext) { + copyString(first = false) + } + + val fstring = bldr.toString +// val expr = c.reify(fstring.format((ids.map(id => Expr(id).eval)) : _*)) +// https://issues.scala-lang.org/browse/SI-5824, therefore + val expr = + Apply( + Select( + Literal(Constant(fstring)), + newTermName("format")), + List(ids: _* ) + ); + + Block(evals.toList, expr) + } + +}
\ No newline at end of file diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index f400f18dab..f11dfb72ae 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -8,7 +8,7 @@ package scala -import collection.mutable.ArrayBuffer +import language.experimental.macros /** A class to support string interpolation. * This class supports string interpolation as outlined in Scala SIP-11. @@ -42,7 +42,7 @@ case class StringContext(parts: String*) { * @throws A `StringContext.InvalidEscapeException` if if a `parts` string contains a backslash (`\`) character * that does not start a valid escape sequence. */ - def s(args: Any*) = { + def s(args: Any*): String = { checkLengths(args: _*) val pi = parts.iterator val ai = args.iterator @@ -82,38 +82,8 @@ case class StringContext(parts: String*) { * string literally. This is achieved by replacing each such occurrence by the * format specifier `%%`. */ - def f(args: Any*) = { - checkLengths(args: _*) - val pi = parts.iterator - val bldr = new java.lang.StringBuilder - def copyString(first: Boolean): Unit = { - val str = treatEscapes(pi.next()) - val strIsEmpty = str.length == 0 - var start = 0 - var idx = 0 - if (!first) { - if (strIsEmpty || (str charAt 0) != '%') - bldr append "%s" - idx = 1 - } - if (!strIsEmpty) { - val len = str.length - while (idx < len) { - if (str(idx) == '%') { - bldr append (str substring (start, idx)) append "%%" - start = idx + 1 - } - idx += 1 - } - bldr append (str substring (start, idx)) - } - } - copyString(first = true) - while (pi.hasNext) { - copyString(first = false) - } - bldr.toString format (args: _*) - } + // The implementation is magically hardwired into `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f` + def f(args: Any*): String = macro ??? } object StringContext { diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala index 8c603dc91b..75707b69b0 100644 --- a/src/library/scala/collection/convert/Wrappers.scala +++ b/src/library/scala/collection/convert/Wrappers.scala @@ -467,4 +467,5 @@ private[collection] trait Wrappers { } } -object Wrappers extends Wrappers +@SerialVersionUID(0 - 5857859809262781311L) +object Wrappers extends Wrappers with Serializable diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 0b592be454..60689d70fe 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -496,6 +496,9 @@ trait Definitions extends api.StandardDefinitions { def MacroInternal_materializeAbsTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeAbsTypeTag) def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag) + lazy val StringContextClass = requiredClass[scala.StringContext] + def StringContext_f = getMemberMethod(StringContextClass, nme.f) + lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature] lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature] diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index c17600ec41..55fa00dd4d 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -135,7 +135,7 @@ class Flags extends ModifierFlags { final val CAPTURED = 1 << 16 // variable is accessed from nested function. Set by LambdaLift. final val LABEL = 1 << 17 // method symbol is a label. Set by TailCall final val INCONSTRUCTOR = 1 << 17 // class symbol is defined in this/superclass constructor. - final val SYNTHETIC = 1 << 21 // symbol is compiler-generated + final val SYNTHETIC = 1 << 21 // symbol is compiler-generated (compare with HIDDEN) final val STABLE = 1 << 22 // functions that are assumed to be stable // (typically, access methods for valdefs) // or classes that do not contain abstract types. @@ -165,6 +165,7 @@ class Flags extends ModifierFlags { // A Java method's type is ``cooked'' by transforming raw types to existentials final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED + final val HIDDEN = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode // ------- shift definitions ------------------------------------------------------- @@ -175,6 +176,11 @@ class Flags extends ModifierFlags { final val AntiShift = 56L // Flags which sketchily share the same slot + // 16: BYNAMEPARAM/M CAPTURED COVARIANT/M + // 17: CONTRAVARIANT/M INCONSTRUCTOR LABEL + // 25: DEFAULTPARAM/M TRAIT/M + // 35: EXISTENTIAL MIXEDIN + // 37: IMPLCLASS PRESUPER/M val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL | IMPLCLASS // ------- late flags (set by a transformer phase) --------------------------------- @@ -283,6 +289,10 @@ class Flags extends ModifierFlags { /** These flags are not pickled */ final val FlagsNotPickled = IS_ERROR | OVERLOADED | LIFTED | TRANS_FLAG | LOCKED | TRIEDCOOKING + // A precaution against future additions to FlagsNotPickled turning out + // to be overloaded flags thus not-pickling more than intended. + assert((OverloadedFlagsMask & FlagsNotPickled) == 0, flagsToString(OverloadedFlagsMask & FlagsNotPickled)) + /** These flags are pickled */ final val PickledFlags = InitialFlags & ~FlagsNotPickled diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index c7c0882209..7ead9d6a1b 100644 --- a/src/reflect/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -92,6 +92,7 @@ trait HasFlags { def isCaseAccessor = hasFlag(CASEACCESSOR) def isDeferred = hasFlag(DEFERRED) def isFinal = hasFlag(FINAL) + def isHidden = hasFlag(HIDDEN) def isImplicit = hasFlag(IMPLICIT) def isInterface = hasFlag(INTERFACE) def isJavaDefined = hasFlag(JAVA) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 4ea9b27da9..60b3a6f436 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -4,9 +4,24 @@ package internal trait StdAttachments { self: SymbolTable => + /** + * Common code between reflect-internal Symbol and Tree related to Attachments. + */ + trait Attachable { + protected var rawatt: base.Attachments { type Pos = Position } = NoPosition + def attachments = rawatt + def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this } + def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } + + // cannot be final due to SynchronizedSymbols + def pos: Position = rawatt.pos + def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) + def setPos(newpos: Position): this.type = { pos = newpos; this } + } + case object BackquotedIdentifierAttachment case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree]) case class MacroExpansionAttachment(original: Tree) -}
\ No newline at end of file +} diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 72a99589d5..22b0908cab 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -662,6 +662,7 @@ trait StdNames { val eval: NameType = "eval" val ex: NameType = "ex" val experimental: NameType = "experimental" + val f: NameType = "f" val false_ : NameType = "false" val filter: NameType = "filter" val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize" diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 3cb9f6ff37..957202e448 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -10,6 +10,7 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer import util.Statistics import Flags._ +import base.Attachments trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ @@ -363,7 +364,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends SymbolContextApiImpl with HasFlags - with Annotatable[Symbol] { + with Annotatable[Symbol] + with Attachable { type AccessBoundaryType = Symbol type AnnotationType = AnnotationInfo @@ -385,7 +387,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def rawowner = _rawowner def rawflags = _rawflags - private var rawpos = initPos + rawatt = initPos val id = nextId() // identity displayed when -uniqid //assert(id != 3390, initName) @@ -398,8 +400,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def validTo = _validTo def validTo_=(x: Period) { _validTo = x} - def pos = rawpos - def setPos(pos: Position): this.type = { this.rawpos = pos; this } def setName(name: Name): this.type = { this.name = asNameType(name) ; this } // Update the surrounding scopes @@ -957,13 +957,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Is this symbol an accessor method for outer? */ final def isOuterAccessor = { - hasFlag(STABLE | SYNTHETIC) && + hasFlag(STABLE | HIDDEN) && originalName == nme.OUTER } /** Is this symbol an accessor method for outer? */ final def isOuterField = { - hasFlag(SYNTHETIC) && + hasFlag(HIDDEN) && originalName == nme.OUTER_LOCAL } @@ -1821,6 +1821,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => setInfo (this.info cloneInfo clone) setAnnotations this.annotations ) + this.attachments.all.foreach(clone.addAttachment) if (clone.thisSym != clone) clone.typeOfThis = (clone.typeOfThis cloneInfo clone) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index dd13dd4c4c..e92d644f4a 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -15,20 +15,13 @@ trait Trees extends api.Trees { self: SymbolTable => private[scala] var nodeCount = 0 - abstract class Tree extends TreeContextApiImpl with Product { + abstract class Tree extends TreeContextApiImpl with Attachable with Product { val id = nodeCount // TODO: add to attachment? nodeCount += 1 Statistics.incCounter(TreesStats.nodeByType, getClass) - @inline final def pos: Position = rawatt.pos - def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) - def setPos(newpos: Position): this.type = { pos = newpos; this } - - private var rawatt: Attachments { type Pos = Position } = NoPosition - def attachments = rawatt - def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this } - def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } + @inline final override def pos: Position = rawatt.pos private[this] var rawtpe: Type = _ @inline final def tpe = rawtpe diff --git a/src/reflect/scala/reflect/makro/Universe.scala b/src/reflect/scala/reflect/makro/Universe.scala index 98046be555..a676f7f1de 100644 --- a/src/reflect/scala/reflect/makro/Universe.scala +++ b/src/reflect/scala/reflect/makro/Universe.scala @@ -5,13 +5,24 @@ abstract class Universe extends scala.reflect.api.Universe { val treeBuild: TreeBuilder { val global: Universe.this.type } + trait AttachableApi { + /** ... */ + def attachments: base.Attachments { type Pos = Position } + + /** ... */ + def addAttachment(attachment: Any): AttachableApi.this.type + + /** ... */ + def removeAttachment[T: ClassTag]: AttachableApi.this.type + } + // Symbol extensions --------------------------------------------------------------- override type Symbol >: Null <: SymbolContextApi /** The extended API of symbols that's supported in macro context universes */ - trait SymbolContextApi extends SymbolApi { this: Symbol => + trait SymbolContextApi extends SymbolApi with AttachableApi { this: Symbol => // [Eugene++ to Martin] should we also add mutability methods here (similarly to what's done below for trees)? // I'm talking about `setAnnotations` and friends @@ -23,7 +34,7 @@ abstract class Universe extends scala.reflect.api.Universe { /** The extended API of trees that's supported in macro context universes */ - trait TreeContextApi extends TreeApi { this: Tree => + trait TreeContextApi extends TreeApi with AttachableApi { this: Tree => /** ... */ def pos_=(pos: Position): Unit @@ -62,15 +73,6 @@ abstract class Universe extends scala.reflect.api.Universe { /** ... */ def setSymbol(sym: Symbol): this.type - - /** ... */ - def attachments: base.Attachments { type Pos = Position } - - /** ... */ - def addAttachment(attachment: Any): this.type - - /** ... */ - def removeAttachment[T: ClassTag]: this.type } override type SymTree >: Null <: Tree with SymTreeContextApi diff --git a/test/files/codelib/code.jar.desired.sha1 b/test/files/codelib/code.jar.desired.sha1 index d2b8d9add9..c4cc74c244 100644 --- a/test/files/codelib/code.jar.desired.sha1 +++ b/test/files/codelib/code.jar.desired.sha1 @@ -1 +1 @@ -e737b123d31eede5594ceda07caafed1673ec472 ?code.jar +e737b123d31eede5594ceda07caafed1673ec472 *code.jar diff --git a/test/files/lib/annotations.jar.desired.sha1 b/test/files/lib/annotations.jar.desired.sha1 index 2b4292d796..ff7bc9425e 100644 --- a/test/files/lib/annotations.jar.desired.sha1 +++ b/test/files/lib/annotations.jar.desired.sha1 @@ -1 +1 @@ -02fe2ed93766323a13f22c7a7e2ecdcd84259b6c ?annotations.jar +02fe2ed93766323a13f22c7a7e2ecdcd84259b6c *annotations.jar diff --git a/test/files/lib/enums.jar.desired.sha1 b/test/files/lib/enums.jar.desired.sha1 index 46cd8e92cf..040dff4487 100644 --- a/test/files/lib/enums.jar.desired.sha1 +++ b/test/files/lib/enums.jar.desired.sha1 @@ -1 +1 @@ -981392dbd1f727b152cd1c908c5fce60ad9d07f7 ?enums.jar +981392dbd1f727b152cd1c908c5fce60ad9d07f7 *enums.jar diff --git a/test/files/lib/genericNest.jar.desired.sha1 b/test/files/lib/genericNest.jar.desired.sha1 index e9321262f2..77e4fec408 100644 --- a/test/files/lib/genericNest.jar.desired.sha1 +++ b/test/files/lib/genericNest.jar.desired.sha1 @@ -1 +1 @@ -b1ec8a095cec4902b3609d74d274c04365c59c04 ?genericNest.jar +b1ec8a095cec4902b3609d74d274c04365c59c04 *genericNest.jar diff --git a/test/files/lib/methvsfield.jar.desired.sha1 b/test/files/lib/methvsfield.jar.desired.sha1 index 8c01532b88..6655f45ddb 100644 --- a/test/files/lib/methvsfield.jar.desired.sha1 +++ b/test/files/lib/methvsfield.jar.desired.sha1 @@ -1 +1 @@ -be8454d5e7751b063ade201c225dcedefd252775 ?methvsfield.jar +be8454d5e7751b063ade201c225dcedefd252775 *methvsfield.jar diff --git a/test/files/lib/nest.jar.desired.sha1 b/test/files/lib/nest.jar.desired.sha1 index 674ca79a5b..056e7ada90 100644 --- a/test/files/lib/nest.jar.desired.sha1 +++ b/test/files/lib/nest.jar.desired.sha1 @@ -1 +1 @@ -cd33e0a0ea249eb42363a2f8ba531186345ff68c ?nest.jar +cd33e0a0ea249eb42363a2f8ba531186345ff68c *nest.jar diff --git a/test/files/lib/scalacheck.jar.desired.sha1 b/test/files/lib/scalacheck.jar.desired.sha1 index e6ed543d73..2f15402d18 100644 --- a/test/files/lib/scalacheck.jar.desired.sha1 +++ b/test/files/lib/scalacheck.jar.desired.sha1 @@ -1 +1 @@ -b6f4dbb29f0c2ec1eba682414f60d52fea84f703 ?scalacheck.jar +b6f4dbb29f0c2ec1eba682414f60d52fea84f703 *scalacheck.jar diff --git a/test/files/neg/stringinterpolation_macro-neg.check b/test/files/neg/stringinterpolation_macro-neg.check new file mode 100644 index 0000000000..8986b899a3 --- /dev/null +++ b/test/files/neg/stringinterpolation_macro-neg.check @@ -0,0 +1,70 @@ +stringinterpolation_macro-neg.scala:8: error: too few parts + new StringContext().f() + ^ +stringinterpolation_macro-neg.scala:9: error: too few arguments for interpolated string + new StringContext("", " is ", "%2d years old").f(s) + ^ +stringinterpolation_macro-neg.scala:10: error: too many arguments for interpolated string + new StringContext("", " is ", "%2d years old").f(s, d, d) + ^ +stringinterpolation_macro-neg.scala:11: error: too few arguments for interpolated string + new StringContext("", "").f() + ^ +stringinterpolation_macro-neg.scala:14: error: type mismatch; + found : String + required: Boolean + f"$s%b" + ^ +stringinterpolation_macro-neg.scala:15: error: type mismatch; + found : String + required: Char + f"$s%c" + ^ +stringinterpolation_macro-neg.scala:16: error: type mismatch; + found : Double + required: Char + f"$f%c" + ^ +stringinterpolation_macro-neg.scala:17: error: type mismatch; + found : String + required: Int + f"$s%x" + ^ +stringinterpolation_macro-neg.scala:18: error: type mismatch; + found : Boolean + required: Int + f"$b%d" + ^ +stringinterpolation_macro-neg.scala:19: error: type mismatch; + found : String + required: Int + f"$s%d" + ^ +stringinterpolation_macro-neg.scala:20: error: type mismatch; + found : Double + required: Int + f"$f%o" + ^ +stringinterpolation_macro-neg.scala:21: error: type mismatch; + found : String + required: Double + f"$s%e" + ^ +stringinterpolation_macro-neg.scala:22: error: type mismatch; + found : Boolean + required: Double + f"$b%f" + ^ +stringinterpolation_macro-neg.scala:27: error: type mismatch; + found : String + required: Int +Note that implicit conversions are not applicable because they are ambiguous: + both value strToInt2 of type String => Int + and value strToInt1 of type String => Int + are possible conversion functions from String to Int + f"$s%d" + ^ +stringinterpolation_macro-neg.scala:30: error: illegal conversion character + f"$s%i" + ^ +15 errors found diff --git a/test/files/neg/stringinterpolation_macro-neg.scala b/test/files/neg/stringinterpolation_macro-neg.scala new file mode 100644 index 0000000000..ac9d97d678 --- /dev/null +++ b/test/files/neg/stringinterpolation_macro-neg.scala @@ -0,0 +1,31 @@ +object Test extends App { + val s = "Scala" + val d = 8 + val b = false + val f = 3.14159 + + // 1) number of arguments + new StringContext().f() + new StringContext("", " is ", "%2d years old").f(s) + new StringContext("", " is ", "%2d years old").f(s, d, d) + new StringContext("", "").f() + + // 2) Interpolation mismatches + f"$s%b" + f"$s%c" + f"$f%c" + f"$s%x" + f"$b%d" + f"$s%d" + f"$f%o" + f"$s%e" + f"$b%f" + + { + implicit val strToInt1 = (s: String) => 1 + implicit val strToInt2 = (s: String) => 2 + f"$s%d" + } + + f"$s%i" +} diff --git a/test/files/neg/t6042.check b/test/files/neg/t6042.check new file mode 100644 index 0000000000..221f06e2c5 --- /dev/null +++ b/test/files/neg/t6042.check @@ -0,0 +1,4 @@ +t6042.scala:7: error: illegal type selection from volatile type a.OpSemExp (with upper bound LazyExp[a.OpSemExp] with _$1) + def foo[AA <: LazyExp[_]](a: AA): a.OpSemExp#Val = ??? // a.OpSemExp is volatile, because of `with This` + ^ +one error found diff --git a/test/files/neg/t6042.scala b/test/files/neg/t6042.scala new file mode 100644 index 0000000000..5a123d17ca --- /dev/null +++ b/test/files/neg/t6042.scala @@ -0,0 +1,8 @@ +trait LazyExp[+This <: LazyExp[This]] { this: This => + type OpSemExp <: LazyExp[OpSemExp] with This + type Val +} + +object Test { + def foo[AA <: LazyExp[_]](a: AA): a.OpSemExp#Val = ??? // a.OpSemExp is volatile, because of `with This` +} diff --git a/test/files/presentation/hyperlinks.flags b/test/files/presentation/hyperlinks.flags deleted file mode 100644 index dc13682c5e..0000000000 --- a/test/files/presentation/hyperlinks.flags +++ /dev/null @@ -1,2 +0,0 @@ -# This test will fail in the new pattern matcher because -# it generates trees whose positions are not transparent diff --git a/test/files/presentation/hyperlinks/Runner.scala b/test/files/presentation/hyperlinks/Runner.scala index 3d19f2d948..61da49a3d7 100644 --- a/test/files/presentation/hyperlinks/Runner.scala +++ b/test/files/presentation/hyperlinks/Runner.scala @@ -1,11 +1,11 @@ import scala.tools.nsc.interactive.tests.InteractiveTest object Test extends InteractiveTest { - override def runTests() { + override def runDefaultTests() { // make sure typer is done.. the virtual pattern matcher might translate // some trees and mess up positions. But we'll catch it red handed! sourceFiles foreach (src => askLoadedTyped(src).get) - super.runTests() + super.runDefaultTests() } }
\ No newline at end of file diff --git a/test/files/presentation/ide-bug-1000469/Runner.scala b/test/files/presentation/ide-bug-1000469/Runner.scala index c53533fddd..1ef3cf9025 100644 --- a/test/files/presentation/ide-bug-1000469/Runner.scala +++ b/test/files/presentation/ide-bug-1000469/Runner.scala @@ -1,5 +1,3 @@ import scala.tools.nsc.interactive.tests._ -object Test extends InteractiveTest { - override val runRandomTests = false -} +object Test extends InteractiveTest
\ No newline at end of file diff --git a/test/files/presentation/ide-bug-1000531.flags b/test/files/presentation/ide-bug-1000531.flags deleted file mode 100644 index 56d026a62d..0000000000 --- a/test/files/presentation/ide-bug-1000531.flags +++ /dev/null @@ -1,18 +0,0 @@ -# This file contains command line options that are passed to the presentation compiler -# Lines starting with # are stripped, and you can split arguments on several lines. - -# The -bootclasspath option is treated specially by the test framework: if it's not specified -# in this file, the presentation compiler will pick up the scala-library/compiler that's on the -# java classpath used to run this test (usually build/pack) - -# Any option can be passed this way, like presentation debug -# -Ypresentation-debug -Ypresentation-verbose - -# the classpath is relative to the current working directory. That means it depends where you're -# running partest from. Run it from the root scala checkout for these files to resolve correctly -# (by default when running 'ant test', or 'test/partest'). Paths use Unix separators, the test -# framework translates them to the platform dependent representation. -# -bootclasspath lib/scala-compiler.jar:lib/scala-library.jar:lib/fjbg.jar - -# the following line would test using the quick compiler -# -bootclasspath build/quick/classes/compiler:build/quick/classes/library:lib/fjbg.jar diff --git a/test/files/presentation/ide-t1000976.check b/test/files/presentation/ide-t1000976.check new file mode 100644 index 0000000000..d58f86d6c6 --- /dev/null +++ b/test/files/presentation/ide-t1000976.check @@ -0,0 +1 @@ +Test OK
\ No newline at end of file diff --git a/test/files/presentation/ide-t1000976.flags b/test/files/presentation/ide-t1000976.flags new file mode 100644 index 0000000000..9a1a05a4f6 --- /dev/null +++ b/test/files/presentation/ide-t1000976.flags @@ -0,0 +1 @@ +-sourcepath src
\ No newline at end of file diff --git a/test/files/presentation/ide-t1000976/Test.scala b/test/files/presentation/ide-t1000976/Test.scala new file mode 100644 index 0000000000..722259d3a1 --- /dev/null +++ b/test/files/presentation/ide-t1000976/Test.scala @@ -0,0 +1,30 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + override def execute(): Unit = { + loadSourceAndWaitUntilTypechecked("A.scala") + val sourceB = loadSourceAndWaitUntilTypechecked("B.scala") + checkErrors(sourceB) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + compiler.askToDoFirst(sourceFile) + val res = new Response[Unit] + compiler.askReload(List(sourceFile), res) + res.get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/ide-t1000976/src/a/A.scala b/test/files/presentation/ide-t1000976/src/a/A.scala new file mode 100644 index 0000000000..fcfef8b525 --- /dev/null +++ b/test/files/presentation/ide-t1000976/src/a/A.scala @@ -0,0 +1,7 @@ +package a + +import d.D._ + +object A { + Seq.empty[Byte].toArray.toSeq +} diff --git a/test/files/presentation/ide-t1000976/src/b/B.scala b/test/files/presentation/ide-t1000976/src/b/B.scala new file mode 100644 index 0000000000..628348cac1 --- /dev/null +++ b/test/files/presentation/ide-t1000976/src/b/B.scala @@ -0,0 +1,7 @@ +package b + +import c.C + +class B { + new C("") +} diff --git a/test/files/presentation/ide-t1000976/src/c/C.scala b/test/files/presentation/ide-t1000976/src/c/C.scala new file mode 100644 index 0000000000..cc23e3eef1 --- /dev/null +++ b/test/files/presentation/ide-t1000976/src/c/C.scala @@ -0,0 +1,3 @@ +package c + +class C(key: String = "", componentStates: String = "") diff --git a/test/files/presentation/ide-t1000976/src/d/D.scala b/test/files/presentation/ide-t1000976/src/d/D.scala new file mode 100644 index 0000000000..d7a48f98d5 --- /dev/null +++ b/test/files/presentation/ide-t1000976/src/d/D.scala @@ -0,0 +1,7 @@ +package d + +import c.C + +object D { + implicit def c2s(c: C): String = "" +} diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala index 857beac7df..a5533a623a 100644 --- a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala +++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala @@ -24,10 +24,7 @@ import scala.tools.nsc.io._ object Test extends InteractiveTest { final val mega = 1024 * 1024 - override def main(args: Array[String]) { - memoryConsumptionTest() - compiler.askShutdown() - } + override def execute(): Unit = memoryConsumptionTest() def batchSource(name: String) = new BatchSourceFile(AbstractFile.getFile(name)) diff --git a/test/files/presentation/t5708/Test.scala b/test/files/presentation/t5708/Test.scala index 96e758d974..bec1131c4c 100644 --- a/test/files/presentation/t5708/Test.scala +++ b/test/files/presentation/t5708/Test.scala @@ -1,5 +1,3 @@ import scala.tools.nsc.interactive.tests.InteractiveTest -object Test extends InteractiveTest { - -}
\ No newline at end of file +object Test extends InteractiveTest
\ No newline at end of file diff --git a/test/files/presentation/visibility/Test.scala b/test/files/presentation/visibility/Test.scala index 96e758d974..bec1131c4c 100644 --- a/test/files/presentation/visibility/Test.scala +++ b/test/files/presentation/visibility/Test.scala @@ -1,5 +1,3 @@ import scala.tools.nsc.interactive.tests.InteractiveTest -object Test extends InteractiveTest { - -}
\ No newline at end of file +object Test extends InteractiveTest
\ No newline at end of file diff --git a/test/files/run/stringinterpolation_macro-run.check b/test/files/run/stringinterpolation_macro-run.check new file mode 100644 index 0000000000..be62c5780b --- /dev/null +++ b/test/files/run/stringinterpolation_macro-run.check @@ -0,0 +1,62 @@ +false +false +true +false +true +FALSE +FALSE +TRUE +FALSE +TRUE +true +false +null +0 +80000000 +4c01926 +NULL +4C01926 +null +NULL +Scala +SCALA +5 +x +x +x +x +x +x +x +x +x +x +x +x +S +120 +120 +120 +120 +120 +120 +120 +120 +120 +120 +120 +120 +120 +42 +3.400000e+00 +3.400000e+00 +3.400000e+00 +3.400000e+00 +3.400000e+00 +3.400000e+00 +3.000000e+00 +3.000000e+00 +05/26/12 +05/26/12 +05/26/12 +05/26/12 diff --git a/test/files/run/stringinterpolation_macro-run.scala b/test/files/run/stringinterpolation_macro-run.scala new file mode 100644 index 0000000000..9c59c334f8 --- /dev/null +++ b/test/files/run/stringinterpolation_macro-run.scala @@ -0,0 +1,103 @@ +object Test extends App { + +// 'b' / 'B' (category: general) +// ----------------------------- +println(f"${null}%b") +println(f"${false}%b") +println(f"${true}%b") +println(f"${new java.lang.Boolean(false)}%b") +println(f"${new java.lang.Boolean(true)}%b") + +println(f"${null}%B") +println(f"${false}%B") +println(f"${true}%B") +println(f"${new java.lang.Boolean(false)}%B") +println(f"${new java.lang.Boolean(true)}%B") + +implicit val stringToBoolean = java.lang.Boolean.parseBoolean(_: String) +println(f"${"true"}%b") +println(f"${"false"}%b") + +// 'h' | 'H' (category: general) +// ----------------------------- +println(f"${null}%h") +println(f"${0.0}%h") +println(f"${-0.0}%h") +println(f"${"Scala"}%h") + +println(f"${null}%H") +println(f"${"Scala"}%H") + +// 's' | 'S' (category: general) +// ----------------------------- +println(f"${null}%s") +println(f"${null}%S") +println(f"${"Scala"}%s") +println(f"${"Scala"}%S") +println(f"${5}") + +// 'c' | 'C' (category: character) +// ------------------------------- +println(f"${120:Char}%c") +println(f"${120:Byte}%c") +println(f"${120:Short}%c") +println(f"${120:Int}%c") +println(f"${new java.lang.Character('x')}%c") +println(f"${new java.lang.Byte(120:Byte)}%c") +println(f"${new java.lang.Short(120:Short)}%c") +println(f"${new java.lang.Integer(120)}%c") + +println(f"${'x' : java.lang.Character}%c") +println(f"${(120:Byte) : java.lang.Byte}%c") +println(f"${(120:Short) : java.lang.Short}%c") +println(f"${120 : java.lang.Integer}%c") + +implicit val stringToChar = (x: String) => x(0) +println(f"${"Scala"}%c") + +// 'd' | 'o' | 'x' | 'X' (category: integral) +// ------------------------------------------ +println(f"${120:Byte}%d") +println(f"${120:Short}%d") +println(f"${120:Int}%d") +println(f"${120:Long}%d") +println(f"${new java.lang.Byte(120:Byte)}%d") +println(f"${new java.lang.Short(120:Short)}%d") +println(f"${new java.lang.Integer(120)}%d") +println(f"${new java.lang.Long(120)}%d") +println(f"${120 : java.lang.Integer}%d") +println(f"${120 : java.lang.Long}%d") +println(f"${BigInt(120)}%d") +println(f"${new java.math.BigInteger("120")}%d") + +{ + implicit val strToShort = (s: String) => java.lang.Short.parseShort(s) + println(f"${"120"}%d") + implicit val strToInt = (s: String) => 42 + println(f"${"120"}%d") +} + +// 'e' | 'E' | 'g' | 'G' | 'f' | 'a' | 'A' (category: floating point) +// ------------------------------------------------------------------ +println(f"${3.4f}%e") +println(f"${3.4}%e") +println(f"${3.4f : java.lang.Float}%e") +println(f"${3.4 : java.lang.Double}%e") +println(f"${BigDecimal(3.4)}%e") +println(f"${new java.math.BigDecimal(3.4)}%e") +println(f"${3}%e") +println(f"${3L}%e") + +// 't' | 'T' (category: date/time) +// ------------------------------- +import java.util.Calendar +import java.util.Locale +val c = Calendar.getInstance(Locale.US) +c.set(2012, Calendar.MAY, 26) +println(f"${c}%TD") +println(f"${c.getTime}%TD") +println(f"${c.getTime.getTime}%TD") + +implicit val strToDate = (x: String) => c +println(f"""${"1234"}%TD""") +} diff --git a/test/files/run/t5974.check b/test/files/run/t5974.check new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/test/files/run/t5974.check @@ -0,0 +1 @@ +ok diff --git a/test/files/run/t5974.scala b/test/files/run/t5974.scala new file mode 100644 index 0000000000..5b99e9f721 --- /dev/null +++ b/test/files/run/t5974.scala @@ -0,0 +1,10 @@ +object Test extends App { + import scala.collection.JavaConverters._ + + def ser(a: AnyRef) = + (new java.io.ObjectOutputStream(new java.io.ByteArrayOutputStream())).writeObject(a) + + val l = java.util.Arrays.asList("pigdog").asScala + ser(l) + println("ok") +} diff --git a/test/files/speclib/instrumented.jar.desired.sha1 b/test/files/speclib/instrumented.jar.desired.sha1 index 24856fe19a..0b8ee593da 100644 --- a/test/files/speclib/instrumented.jar.desired.sha1 +++ b/test/files/speclib/instrumented.jar.desired.sha1 @@ -1 +1 @@ -474d8c20ab31438d5d4a2ba6bc07ebdcdb530b50 ?instrumented.jar +474d8c20ab31438d5d4a2ba6bc07ebdcdb530b50 *instrumented.jar |