summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-09-29 13:55:04 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-09-29 13:55:04 +0000
commit5f4a754228beeb302994e5597e6d93cf2a0e39e3 (patch)
tree490df79f19b9293cb10c16a03d56f3acad17cbbe
parent5b79a0442369d55094244e08f8a2c8c2ff117007 (diff)
downloadscala-5f4a754228beeb302994e5597e6d93cf2a0e39e3.tar.gz
scala-5f4a754228beeb302994e5597e6d93cf2a0e39e3.tar.bz2
scala-5f4a754228beeb302994e5597e6d93cf2a0e39e3.zip
Merged revisions 23127-23128,23139,23141 via sv...
Merged revisions 23127-23128,23139,23141 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r23127 | moors | 2010-09-28 17:46:36 +0200 (Tue, 28 Sep 2010) | 3 lines closes #3865: scaladoc now prints anonymous type functions since they may occur due to normalization of type constructor arguments of inferred types review by dubochet ........ r23128 | moors | 2010-09-28 17:46:41 +0200 (Tue, 28 Sep 2010) | 3 lines closes #3859. need to instantiate type parameters to nothing explicitly in manifestOfType's searchresult rather than relying on later calls to instantiate. review by odersky ........ r23139 | odersky | 2010-09-29 11:57:49 +0200 (Wed, 29 Sep 2010) | 1 line Closes #3875. Review by vigdorchick. ........ r23141 | odersky | 2010-09-29 15:42:47 +0200 (Wed, 29 Sep 2010) | 1 line Changed Response so that get does what it did before, and get(TIMEOUT) returns provisional results if it can. Review by vigdorchick. ........
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala12
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala21
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Response.scala67
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--test/files/pos/t3859.scala4
8 files changed, 87 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index e36df22435..f7c5c5d724 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -402,7 +402,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
else if (bSym.isAliasType)
Some(new NonTemplateMemberImpl(bSym, inTpl) with HigherKindedImpl with AliasType {
override def isAliasType = true
- def alias = makeType(appliedType(sym.tpe, sym.info.typeParams map {_.tpe}).normalize, inTpl, sym)
+ def alias = makeType(sym.tpe.dealias, inTpl, sym)
})
else if (bSym.isPackage)
inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) }
@@ -536,8 +536,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
nameBuffer append " {...}" // TODO: actually print the refinement
}
/* Polymorphic types */
- case PolyType(tparams, result) if (!tparams.isEmpty) =>
- throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
+ case PolyType(tparams, result) if tparams nonEmpty =>
+// throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
+ def typeParamsToString(tps: List[Symbol]): String = if(tps isEmpty) "" else
+ tps.map{tparam =>
+ tparam.varianceString + tparam.name + typeParamsToString(tparam.typeParams)
+ }.mkString("[", ", ", "]")
+ nameBuffer append typeParamsToString(tparams)
+ appendType0(result)
case PolyType(tparams, result) if (tparams.isEmpty) =>
nameBuffer append '⇒'
appendType0(result)
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 1772f6f722..0ae137b23b 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -91,7 +91,7 @@ trait CompilerControl { self: Global =>
/** Make sure a set of compilation units is loaded and parsed.
* Return () to syncvar `result` on completion.
*/
- def askReload(sources: List[SourceFile], result: Response[Unit]) =
+ def askReload(sources: Seq[SourceFile], result: Response[Unit]) =
scheduler postWorkItem new WorkItem {
def apply() = reload(sources, result)
override def toString = "reload "+sources
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 59221eb348..e47c511260 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -33,7 +33,7 @@ self =>
* All units in firsts are typechecked before any unit not in this list
* Modified by askToDoFirst, reload, typeAtTree.
*/
- var firsts: List[SourceFile] = List()
+ var firsts: Seq[SourceFile] = Seq()
/** A map of all loaded files to the rich compilation units that correspond to them.
*/
@@ -210,9 +210,11 @@ self =>
/** The current presentation compiler runner */
private var compileRunner = newRunnerThread
+ private var threadId = 1
+
/** Create a new presentation compiler runner.
*/
- def newRunnerThread: Thread = new Thread("Scala Presentation Compiler") {
+ def newRunnerThread: Thread = new Thread("Scala Presentation Compiler V"+threadId) {
override def run() {
try {
while (true) {
@@ -240,6 +242,7 @@ self =>
}
}
}
+ threadId += 1
start()
}
@@ -254,7 +257,7 @@ self =>
val prefix = firsts map unitOf
- val units = prefix ::: (unitOfFile.values.toList diff prefix) filter (!_.isUpToDate)
+ val units = prefix ++ (unitOfFile.values.toSeq diff prefix) filter (!_.isUpToDate)
recompile(units)
@@ -284,7 +287,7 @@ self =>
/** Make sure symbol and type attributes are reset and recompile units.
*/
- def recompile(units: List[RichCompilationUnit]) {
+ def recompile(units: Seq[RichCompilationUnit]) {
for (unit <- units) {
reset(unit)
if (debugIDE) inform("parsing: "+unit)
@@ -295,7 +298,7 @@ self =>
activeLocks = 0
currentTyperRun.typeCheck(unit)
unit.status = currentRunId
- syncTopLevelSyms(unit)
+ if (!unit.isJava) syncTopLevelSyms(unit)
}
}
@@ -311,8 +314,8 @@ self =>
}
/** Move list of files to front of firsts */
- def moveToFront(fs: List[SourceFile]) {
- firsts = fs ::: (firsts diff fs)
+ def moveToFront(fs: Seq[SourceFile]) {
+ firsts = fs ++ (firsts diff fs)
}
// ----------------- Implementations of client commands -----------------------
@@ -348,7 +351,7 @@ self =>
}
/** Make sure a set of compilation units is loaded and parsed */
- def reloadSources(sources: List[SourceFile]) {
+ def reloadSources(sources: Seq[SourceFile]) {
currentTyperRun = newTyperRun
for (source <- sources) {
val unit = new RichCompilationUnit(source)
@@ -359,7 +362,7 @@ self =>
}
/** Make sure a set of compilation units is loaded and parsed */
- def reload(sources: List[SourceFile], response: Response[Unit]) {
+ def reload(sources: Seq[SourceFile], response: Response[Unit]) {
respond(response)(reloadSources(sources))
if (outOfDate) throw FreshRunReq // cancel background compile
else outOfDate = true // proceed normally and enable new background compile
diff --git a/src/compiler/scala/tools/nsc/interactive/Response.scala b/src/compiler/scala/tools/nsc/interactive/Response.scala
index 96e474a34a..56a48e44cd 100644
--- a/src/compiler/scala/tools/nsc/interactive/Response.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Response.scala
@@ -1,8 +1,6 @@
package scala.tools.nsc
package interactive
-import scala.concurrent.SyncVar
-
/** Typical interaction, given a predicate <user-input>, a function <display>,
* and an exception handler <handle>:
*
@@ -19,49 +17,80 @@ import scala.concurrent.SyncVar
*/
class Response[T] {
- private val data = new SyncVar[Either[T, Throwable]]
+ private var data: Option[Either[T, Throwable]] = None
private var complete = false
private var cancelled = false
/** Set provisional data, more to come
*/
- def setProvisionally(x: T) =
- data.set(Left(x))
+ def setProvisionally(x: T) = synchronized {
+ data = Some(Left(x))
+ }
- /** Set final data, and mark resposne as complete.
+ /** Set final data, and mark response as complete.
*/
- def set(x: T) = data.synchronized {
- data.set(Left(x))
+ def set(x: T) = synchronized {
+ data = Some(Left(x))
complete = true
+ notifyAll()
}
- def raise(exc: Throwable) = data.synchronized {
- data.set(Right(exc))
+ /** Store raised exception in data, and mark response as complete.
+ */
+ def raise(exc: Throwable) = synchronized {
+ data = Some(Right(exc))
complete = true
+ notifyAll()
}
- /** Get data, wait as long as necessary
+ /** Get final data, wait as long as necessary.
+ * When interrupted will return with Right(InterruptedException)
*/
- def get: Either[T, Throwable] = data.get
+ def get: Either[T, Throwable] = synchronized {
+ while (!complete) {
+ try {
+ wait()
+ } catch {
+ case exc: InterruptedException => raise(exc)
+ }
+ }
+ data.get
+ }
/** Optionally get data within `timeout` milliseconds.
+ * When interrupted will return with Some(Right(InterruptedException))
+ * When timeout ends, will return last stored provisional result,
+ * or else None if no provisional result was stored.
*/
- def get(timeout: Long): Option[Either[T, Throwable]] = data.get(timeout)
+ def get(timeout: Long): Option[Either[T, Throwable]] = {
+ val start = System.currentTimeMillis
+ var current = start
+ while (!complete && start + timeout > current) {
+ try {
+ wait(timeout - (current - start))
+ } catch {
+ case exc: InterruptedException => raise(exc)
+ }
+ current = System.currentTimeMillis
+ }
+ data
+ }
/** Final data set was stored
*/
- def isComplete = data.synchronized { complete }
+ def isComplete = synchronized { complete }
- /** Cancel action computing this response
+ /** Cancel action computing this response (Only the
+ * party that calls get on a response may cancel).
*/
- def cancel() = data.synchronized { cancelled = true }
+ def cancel() = synchronized { cancelled = true }
/** A cancel request for this response has been issued
*/
- def isCancelled = data.synchronized { cancelled }
+ def isCancelled = synchronized { cancelled }
- def clear() = data.synchronized {
- data.unset()
+ def clear() = synchronized {
+ data = None
complete = false
cancelled = false
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 32db64679d..a05bedc97a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -218,6 +218,8 @@ trait Definitions extends reflect.generic.StandardDefinitions {
lazy val Array_clone = getMember(ArrayClass, nme.clone_)
lazy val ArrayModule = getModule("scala.Array")
+ def isArray_Apply(sym: Symbol): Boolean = sym.owner == ArrayModule.moduleClass && sym.name == nme.apply
+
// reflection / structural types
lazy val SoftReferenceClass = getClass("java.lang.ref.SoftReference")
lazy val WeakReferenceClass = getClass("java.lang.ref.WeakReference")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 392223e1e2..ad39736ba3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -789,7 +789,7 @@ self: Analyzer =>
* reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?
*/
- private def manifestOfType(tp: Type, full: Boolean): Tree = {
+ private def manifestOfType(tp: Type, full: Boolean): SearchResult = {
/** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree =
@@ -814,8 +814,10 @@ self: Analyzer =>
inferImplicit(tree, appliedType(manifestClass.typeConstructor, List(tp)), true, false, context).tree
def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
+ def mot(tp0: Type)(implicit from: List[Symbol] = List(), to: List[Type] = List()): SearchResult = {
+ implicit def wrapResult(tree: Tree): SearchResult =
+ if (tree == EmptyTree) SearchFailure else new SearchResult(tree, new TreeTypeSubstituter(from, to))
- def mot(tp0: Type): Tree = {
val tp1 = tp0.normalize
tp1 match {
case ThisType(_) | SingleType(_, _) if !(tp1 exists {tp => tp.typeSymbol.isExistentiallyBound}) => // can't generate a reference to a value that's abstracted over by an existential
@@ -849,7 +851,7 @@ self: Analyzer =>
manifestFactoryCall("wildcardType", tp,
findManifest(tp.bounds.lo), findManifest(tp.bounds.hi))
} else if(undetParams contains sym) { // looking for a manifest of a type parameter that hasn't been inferred by now, can't do much, but let's not fail
- mot(NothingClass.tpe) // TODO: should we include the mapping from sym -> NothingClass.tpe in the SearchResult? (it'll get instantiated to nothing anyway, I think)
+ mot(NothingClass.tpe)(sym :: from, NothingClass.tpe :: to) // #3859: need to include the mapping from sym -> NothingClass.tpe in the SearchResult
} else {
EmptyTree // a manifest should have been found by normal searchImplicit
}
@@ -875,13 +877,12 @@ self: Analyzer =>
*/
private def implicitManifestOrOfExpectedType(pt: Type): SearchResult = pt.dealias match {
case TypeRef(_, FullManifestClass, List(arg)) =>
- wrapResult(manifestOfType(arg, true))
+ manifestOfType(arg, true)
case TypeRef(_, PartialManifestClass, List(arg)) =>
- wrapResult(manifestOfType(arg, false))
+ manifestOfType(arg, false)
case TypeRef(_, OptManifestClass, List(arg)) =>
- val itree = manifestOfType(arg, false)
- wrapResult(if (itree == EmptyTree) gen.mkAttributedRef(NoManifest)
- else itree)
+ val res = manifestOfType(arg, false)
+ if (res == SearchFailure) wrapResult(gen.mkAttributedRef(NoManifest)) else res
case TypeRef(_, tsym, _) if (tsym.isAbstractType) =>
implicitManifestOrOfExpectedType(pt.bounds.lo)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d58f881200..9efe53d96a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2658,7 +2658,7 @@ trait Typers { self: Analyzer =>
// and Array.apply(x: Int, xs: Int*): Array[Int] (and similar)
case Apply(fun, args) =>
val typedFun = typed(fun, funMode(mode), WildcardType)
- if (typedFun.symbol.owner == ArrayModule.moduleClass && typedFun.symbol.name == nme.apply)
+ if (isArray_Apply(typedFun.symbol))
pt match {
case TypeRef(_, ArrayClass, targ :: _) =>
trees2ConstArg(args, targ)
@@ -3384,7 +3384,7 @@ trait Typers { self: Analyzer =>
res.tpe = res.tpe.notNull
}
*/
- if (fun2.symbol == Array_apply) {
+ if (isArray_Apply(fun2.symbol)) {
val checked = gen.mkCheckInit(res)
// this check is needed to avoid infinite recursion in Duplicators
// (calling typed1 more than once for the same tree)
diff --git a/test/files/pos/t3859.scala b/test/files/pos/t3859.scala
new file mode 100644
index 0000000000..83d4c37b29
--- /dev/null
+++ b/test/files/pos/t3859.scala
@@ -0,0 +1,4 @@
+class Test {
+ def foo: Unit = bar(Array(): _*)
+ def bar(values: AnyRef*): Unit = ()
+} \ No newline at end of file