diff options
author | Martin Odersky <odersky@gmail.com> | 2008-09-04 16:33:51 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-09-04 16:33:51 +0000 |
commit | 3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5 (patch) | |
tree | 39e044e9c789277e68c89a72533088dc4190e8d7 /src | |
parent | 743edeefd44939ada6e81c5936cc04f7c6601931 (diff) | |
download | scala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.tar.gz scala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.tar.bz2 scala-3e0cd7e7488477e60eb8d12ffeea1b3dc02433a5.zip |
now checking for volatile types.
Diffstat (limited to 'src')
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 <prefix>.<sym.name>.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 } } |