summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-09-04 16:33:51 +0000
committerMartin Odersky <odersky@gmail.com>2008-09-04 16:33:51 +0000
commit3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5 (patch)
tree39e044e9c789277e68c89a72533088dc4190e8d7 /src
parent743edeefd44939ada6e81c5936cc04f7c6601931 (diff)
downloadscala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.tar.gz
scala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.tar.bz2
scala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.zip
now checking for volatile types.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala38
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala38
5 files changed, 84 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index 6bac62aefd..55a561b8cf 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -93,26 +93,30 @@ class StandardCompileClient {
}
val socket = if (serverAdr == "") compileSocket.getOrCreateSocket(vmArgs, !shutdown)
else compileSocket.getSocket(serverAdr)
- if (shutdown && (socket==null)) {
- Console.println("[No compilation server running.]")
- return 0
- }
- val out = new PrintWriter(socket.getOutputStream(), true)
- val in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
- out.println(compileSocket.getPassword(socket.getPort()))
- out.println(args.mkString("", "\0", ""))
var sawerror = false
- var fromServer = in.readLine()
- while (fromServer ne null) {
- if (compileSocket.errorPattern.matcher(fromServer).matches)
+ if (socket == 0) {
+ if (shutdown) {
+ Console.println("[No compilation server running.]")
+ } else {
+ Console.println("Compilation failed.")
sawerror = true
- Console.println(fromServer)
- fromServer = in.readLine()
+ }
+ } else {
+ val out = new PrintWriter(socket.getOutputStream(), true)
+ val in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
+ out.println(compileSocket.getPassword(socket.getPort()))
+ out.println(args.mkString("", "\0", ""))
+ var fromServer = in.readLine()
+ while (fromServer ne null) {
+ if (compileSocket.errorPattern.matcher(fromServer).matches)
+ sawerror = true
+ Console.println(fromServer)
+ fromServer = in.readLine()
+ }
+ in.close()
+ out.close()
+ socket.close()
}
- in.close()
- out.close()
- socket.close()
-
if (sawerror) 1 else 0
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index ed68e42341..5f2b5c76c8 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1703,6 +1703,9 @@ trait Parsers extends NewScanners with MarkupParsers {
val vds = new ListBuffer[List[ValDef]]
val pos = inCurrentPos
newLineOptWhenFollowedBy(LPAREN)
+ if (ofCaseClass && inToken != LPAREN)
+ deprecationWarning(in.currentPos, "case classes without a parameter list have been deprecated;\n"+
+ "use either case objects or case classes with `()' as parameter list.")
while (implicitmod == 0 && inToken == LPAREN) {
inNextToken
vds += paramClause()
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 59854137ed..3365555ed6 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -268,7 +268,7 @@ trait Symbols {
/** Does this symbol denote a stable value? */
final def isStable =
- isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE))
+ isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) && !tpe.isVolatile
def isDeferred =
hasFlag(DEFERRED) && !isClass
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 1b93f17cd0..f50f82d5b1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -143,6 +143,7 @@ trait Types {
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
override def isStable: Boolean = underlying.isStable
+ override def isVolatile = underlying.isVolatile
override def finalResultType = underlying.finalResultType
override def paramSectionCount = underlying.paramSectionCount
override def paramTypes = underlying.paramTypes
@@ -210,6 +211,14 @@ trait Types {
/** Does this type denote a stable reference (i.e. singleton type)? */
def isStable: Boolean = false
+ /** Is this type dangerous (i.e. it might contain conflicting
+ * type information when empty, so that it can be constructed
+ * so that type unsoundness results.) A dangerous type has an underlying
+ * type of the form T_1 with T_n { decls }, where one of the
+ * T_i (i > 1) is an abstract type.
+ */
+ def isVolatile: Boolean = false
+
/** Is this type guaranteed not to have `null' as a value? */
def isNotNull: Boolean = false
@@ -840,7 +849,8 @@ trait Types {
abstract class SingletonType extends SubType with SimpleTypeProxy {
def supertype = underlying
override def isTrivial = false
- override def isStable = true
+ override def isStable = !underlying.isVolatile
+ override def isVolatile = underlying.isVolatile
override def widen: Type = underlying.widen
override def baseTypeSeq: BaseTypeSeq = {
if (util.Statistics.enabled) singletonBaseTypeSeqCount += 1
@@ -934,6 +944,7 @@ trait Types {
override def isStable = true
override def safeToString = "<param "+level+"."+paramId+">"
override def kind = "DeBruijnIndex"
+ // todo: this should be a subtype, which forwards to underlying
}
/** A class for singleton types of the form &lt;prefix&gt;.&lt;sym.name&gt;.type.
@@ -1148,6 +1159,11 @@ trait Types {
decls))
else super.normalize
+ override def isVolatile =
+ !parents.isEmpty &&
+ (!parents.tail.isEmpty || !decls.isEmpty) &&
+ (parents exists (_.typeSymbol.isAbstractType))
+
override def kind = "RefinedType"
}
@@ -1337,6 +1353,10 @@ trait Types {
sym.isAbstractType && (sym.info.bounds.hi.typeSymbol isSubClass SingletonClass)
}
+ override def isVolatile: Boolean = {
+ sym.isAbstractType && transform(sym.info.bounds.hi).isVolatile ||
+ sym.isAliasType && sym.info.normalize.isVolatile
+ }
override val isTrivial: Boolean =
pre.isTrivial && !sym.isTypeParameter && args.forall(_.isTrivial)
@@ -1621,6 +1641,7 @@ A type's typeSymbol should never be inspected directly.
override def baseClasses: List[Symbol] = resultType.baseClasses
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def narrow: Type = resultType.narrow
+ override def isVolatile = resultType.isVolatile
override def deconst =
if (inIDE) PolyType(typeParams, resultType.deconst)
@@ -1798,6 +1819,7 @@ A type's typeSymbol should never be inspected directly.
else constr.inst.toString
}
override def isStable = origin.isStable
+ override def isVolatile = origin.isVolatile
override def kind = "TypeVar"
}
@@ -3627,8 +3649,10 @@ A type's typeSymbol should never be inspected directly.
true
case (_, RefinedType(parents2, ref2)) =>
(parents2 forall (tp2 => tp1 <:< tp2)) &&
- (ref2.toList forall tp1.specializes) &&
+ (ref2.toList forall tp1.specializes) /* &&
+ removed, replaced by stricter condition on stable values.
(tp1.typeSymbol != NullClass || !parents2.exists(_.typeSymbol.isAbstractType))
+*/
case (ExistentialType(_, _), _) =>
try {
skolemizationLevel += 1
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 529ec0444c..406e056128 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -253,7 +253,32 @@ trait Typers { self: Analyzer =>
*/
def checkStable(tree: Tree): Tree =
if (treeInfo.isPureExpr(tree)) tree
- else errorTree(tree, "stable identifier required, but " + tree + " found.")
+ else errorTree(
+ tree,
+ "stable identifier required, but "+tree+" found."+
+ (if (isStableExceptVolatile(tree)) {
+ val tpe = tree.symbol.tpe match {
+ case PolyType(_, rtpe) => rtpe
+ case t => t
+ }
+ "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile."
+ } else ""))
+
+ /** Would tree be a stable (i.e. a pure expression) if the type
+ * of its symbol was not volatile?
+ */
+ private def isStableExceptVolatile(tree: Tree) = {
+ tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
+ { val savedTpe = tree.symbol.info
+ val savedSTABLE = tree.symbol getFlag STABLE
+ tree.symbol setInfo AnyRefClass.tpe
+ tree.symbol setFlag STABLE
+ val result = treeInfo.isPureExpr(tree)
+ tree.symbol setInfo savedTpe
+ tree.symbol setFlag savedSTABLE
+ result
+ }
+ }
/** Check that `tpt' refers to a non-refinement class type */
def checkClassType(tpt: Tree, existentialOK: Boolean) {
@@ -671,7 +696,9 @@ trait Typers { self: Analyzer =>
(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType)))*/ { // (4.2)
if (settings.debug.value) log("eta-expanding "+tree+":"+tree.tpe+" to "+pt)
checkParamsConvertible(tree.pos, tree.tpe)
- typed(etaExpand(context.unit, tree), mode, pt)
+ val tree1 = etaExpand(context.unit, tree)
+// println("eta "+tree+" ---> "+tree1+":"+tree1.tpe)
+ typed(tree1, mode, pt)
} else if (!meth.isConstructor && mt.paramTypes.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt)
} else if (context.implicitsEnabled) {
@@ -2430,17 +2457,18 @@ trait Typers { self: Analyzer =>
.setOriginal(tpt1) /* .setPos(tpt1.pos) */
.setType(appliedType(tpt1.tpe, context.undetparams map (_.tpe)))
}
+ /** If current tree <tree> appears in <val x(: T)? = <tree>>
+ * return `tp with x.type' else return `tp'.
+ */
def narrowRhs(tp: Type) = {
var sym = context.tree.symbol
if (sym != null && sym != NoSymbol && sym.owner.isClass && sym.getter(sym.owner) != NoSymbol)
sym = sym.getter(sym.owner)
context.tree match {
- case ValDef(_, _, _, Apply(Select(`tree`, _), _)) if (sym.isStable) =>
-// println("narrowing...")
+ case ValDef(mods, _, _, Apply(Select(`tree`, _), _)) if !(mods hasFlag MUTABLE) =>
val pre = if (sym.owner.isClass) sym.owner.thisType else NoPrefix
intersectionType(List(tp, singleType(pre, sym)))
case _ =>
-// println("no narrow: "+sym+" "+sym.isStable+" "+context.tree+"//"+tree)
tp
}
}