diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala | 20 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala | 36 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 51 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 18 | ||||
-rw-r--r-- | src/library/scala/List.scala | 34 | ||||
-rw-r--r-- | src/library/scala/Responder.scala | 2 | ||||
-rw-r--r-- | src/library/scala/collection/Map.scala | 4 | ||||
-rw-r--r-- | src/library/scala/collection/Set.scala | 4 | ||||
-rw-r--r-- | src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala | 8 | ||||
-rwxr-xr-x | test/files/neg/t0152.scala | 13 | ||||
-rwxr-xr-x | test/files/pos/listpattern.scala | 8 |
13 files changed, 129 insertions, 76 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index c969dc2f52..53d02d4569 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -161,7 +161,9 @@ abstract class Pickler extends SubComponent { case TypeBounds(lo, hi) => putType(lo); putType(hi) case RefinedType(parents, decls) => - putSymbol(tp.typeSymbol); putTypes(parents); putSymbols(decls.toList) + val rclazz = tp.typeSymbol + assert(decls.elements forall (_.owner == rclazz)) + putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList) case ClassInfoType(parents, decls, clazz) => putSymbol(clazz); putTypes(parents); putSymbols(decls.toList) case MethodType(formals, restpe) => diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala index c8fbe40009..ce4c99ec25 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -25,9 +25,13 @@ abstract class UnPickler { val global: Global import global._ - /** - * @param bytes bytearray from which we unpickle - * @param filename filename associated with bytearray, only used for error messages + /** Unpickle symbol table information descending from a class and/or module root + * from an array of bytes. + * @param bytes bytearray from which we unpickle + * @param offset offset from which unpickling starts + * @param classroot the top-level class which is unpickled, or NoSymbol if unapplicable + * @param moduleroot the top-level module which is unpickled, or NoSymbol if unapplicable + * @param filename filename associated with bytearray, only used for error messages */ def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) { try { @@ -44,8 +48,14 @@ abstract class UnPickler { private class UnPickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol) extends PickleBuffer(bytes, offset, -1) { if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot) checkVersion() + + /** A map from entry numbers to array offsets */ private val index = createIndex + + /** A map from entry numbers to symbols, types, or annotations */ private val entries = new Array[AnyRef](index.length) + + /** A map from symbols to their associated `decls' scopes */ private val symScopes = new HashMap[Symbol, Scope] for (i <- 0 until index.length) { @@ -55,7 +65,7 @@ abstract class UnPickler { if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug - private def checkVersion() = { + private def checkVersion() { val major = readNat() val minor = readNat() if (major != MajorVersion || minor > MinorVersion) @@ -65,7 +75,7 @@ abstract class UnPickler { "\n found: " + major + "." + minor) } - /** The scope associated with given symbol */ + /** The `decls' scope associated with given symbol */ private def symScope(sym: Symbol)(f : => Scope) = symScopes.get(sym) match { case None => val s = f; symScopes(sym) = s; s case Some(s) => s diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index cd48899c17..55c8023ed3 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -415,23 +415,24 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter //assert(nselector.tpe =:= selector.tpe) //val ncases = transformCaseDefs(cases) - def makeGuardDef(vs:SymList, guard:Tree) = { - import symtab.Flags._ - val gdname = cunit.fresh.newName("gd") - val fmls = new ListBuffer[Type] - val method = currentOwner.newMethod(mch.pos, gdname) setFlag (SYNTHETIC) - var vs1 = vs; while (vs1 ne Nil) { - fmls += vs1.head.tpe - vs1 = vs1.tail + def makeGuardDef(vs:SymList, guard:Tree) = { + import symtab.Flags._ + val gdname = cunit.fresh.newName("gd") + val fmls = new ListBuffer[Type] + val method = currentOwner.newMethod(mch.pos, gdname) setFlag (SYNTHETIC) + var vs1 = vs; while (vs1 ne Nil) { + fmls += vs1.head.tpe + vs1 = vs1.tail + } + val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe) + method setInfo tpe + localTyper. + typed { + DefDef(method, + {vparamss => + new ChangeOwnerTraverser(currentOwner, method).traverse(guard); + new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})} } - val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe) - method setInfo tpe - localTyper. - typed { DefDef(method, - {vparamss => - new ChangeOwnerTraverser(currentOwner, method).traverse(guard); - new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})} - } val nguard = new ListBuffer[Tree] val ncases = new ListBuffer[CaseDef] @@ -468,10 +469,13 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter //Console.println("TransMatcher selector.tpe ="+selector.tpe+")") //Console.println("TransMatcher resultType ="+resultType+")") + //println("handle pattern = "+nselector+"/"+ncases.toList+"/"+currentOwner+"/"+tree.tpe) val t_untyped = handlePattern(nselector, ncases.toList, checkExhaustive, currentOwner, transform) + //println("t_untyped = "+t_untyped) try { //Console.println("t_untyped "+t_untyped.toString()) val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) } + //println("t_typed = "+t) //t = transform(t) //val t = atPos(tree.pos) { typed(t_untyped, resultType) } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 5427debfd0..4133a914b0 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -46,7 +46,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { //@MAT: uncurry and uncurryType fully expand type aliases in their input and output // note: don't normalize higher-kined types -- @M TODO: maybe split those uses of normalize? // OTOH, should be a problem as calls to normalize only occur on types with kind * in principle (in well-typed programs) - private def expandAlias(tp: Type): Type = if(!tp.isHigherKinded) tp.normalize else tp + private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp private val uncurry: TypeMap = new TypeMap { def apply(tp0: Type): Type = {val tp=expandAlias(tp0); tp match { @@ -310,6 +310,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { Typed( New(TypeTree(anonClass.tpe), List(List())), TypeTree(fun.tpe))) + } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 695cb60f5e..df34651883 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -316,41 +316,38 @@ abstract class RefChecks extends InfoTransform { val seenTypes = new Array[Type](clazz.info.closure.length) var seenCaseClass = if (clazz hasFlag CASE) clazz else NoSymbol - def validateTypes(tps: List[Type], includeSuper: Boolean) { - if (!tps.isEmpty) { - for (val tp <- tps.tail.reverse) validateType(tp, false); - if (includeSuper) validateType(tps.head, true); - } - } - - def validateType(tp: Type, includeSuper: Boolean) { + /** validate all base types of a class in reverse linear order. */ + def validateType(tp: Type) { val baseClass = tp.typeSymbol if (baseClass.isClass) { val index = clazz.info.closurePos(baseClass) if (index >= 0) { - if ((seenTypes(index) ne null) && !(seenTypes(index) <:< tp)) - unit.error(clazz.pos, "illegal inheritance;\n " + clazz + - " inherits different type instances of " + baseClass + - ":\n" + tp + " and " + seenTypes(index)); - seenTypes(index) = tp; - // check that case classes do not inherit from case classes - if (baseClass hasFlag CASE) { - if (seenCaseClass != NoSymbol && seenCaseClass != baseClass) - unit.error(clazz.pos, "implementation restriction: case " + - seenCaseClass + " and case " + baseClass + - " cannot be combined in one object"); - seenCaseClass = baseClass + if (seenTypes(index) ne null) { + if (!(seenTypes(index) <:< tp)) { + unit.error(clazz.pos, "illegal inheritance;\n " + clazz + + " inherits different type instances of " + baseClass + + ":\n" + tp + " and " + seenTypes(index)); + } + } else { + seenTypes(index) = tp + // check that case classes do not inherit from case classes + if (baseClass hasFlag CASE) { + if (seenCaseClass != NoSymbol && seenCaseClass != baseClass) + unit.error(clazz.pos, "implementation restriction: case " + + seenCaseClass + " and case " + baseClass + + " cannot be combined in one object"); + seenCaseClass = baseClass + } + // check that inner classes do not inherit from Annotation + if (baseClass == ClassfileAnnotationClass) + if (!clazz.owner.isPackageClass) + unit.error(clazz.pos, "inner classes cannot be classfile annotations") } - // check that inner classes do not inherit from Annotation - if (baseClass == ClassfileAnnotationClass) - if (!clazz.owner.isPackageClass) - unit.error(clazz.pos, "inner classes cannot be classfile annotations") + tp.parents foreach validateType } - validateTypes(tp.parents, includeSuper) } } - - validateTypes(clazz.info.parents, true) + validateType(clazz.tpe) } // Variance Checking -------------------------------------------------------- diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9737cc906b..ecba9bb44f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1336,7 +1336,7 @@ trait Typers { self: Analyzer => val thistp = tp.typeSymbol.thisType for (sym <- clazz.info.decls.toList) { if (sym.isPublic && !sym.isClass && !sym.isConstructor) - addMember(thistp, tp, sym) + addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info)) } tp } @@ -2801,19 +2801,9 @@ trait Typers { self: Analyzer => case UnApply(fun, args) => val fun1 = typed(fun) - var tpes = fun.symbol.name match { - case nme.unapply => unapplyTypeListFromReturnType (fun.tpe) - case nme.unapplySeq => unapplyTypeListFromReturnTypeSeq(fun.tpe) - } - var as = args; while(as ne Nil) { // bq: typing a pattern never changes the tree - typedPattern(as.head, tpes.head match { - case TypeRef(_,sym,targs) if sym eq definitions.RepeatedParamClass => targs.head - case tpe => tpe - }) - as = as.tail; tpes = tpes.tail - } - //val args1 = List.mapConserve(args)(typedPattern(_, WildcardType)) - copy.UnApply(tree, fun1, args) setType pt + val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length) + val args1 = List.map2(args, tpes)(typedPattern(_, _)) + copy.UnApply(tree, fun1, args1) setType pt case ArrayValue(elemtpt, elems) => typedArrayValue(elemtpt, elems) diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala index 38028b7385..537f649a8a 100644 --- a/src/library/scala/List.scala +++ b/src/library/scala/List.scala @@ -456,9 +456,14 @@ sealed abstract class List[+A] extends Seq[A] { * @param prefix the prefix to reverse and then prepend * @return the concatenation of the reversed prefix and the current list. */ - def reverse_:::[B >: A](prefix: List[B]): List[B] = prefix match { - case Nil => this - case head :: tail => (head :: this).reverse_:::(tail) + def reverse_:::[B >: A](prefix: List[B]): List[B] = { + var these: List[B] = this + var pres = prefix + while (!pres.isEmpty) { + these = pres.head :: these + pres = pres.tail + } + these } /** Returns the number of elements in the list. @@ -540,8 +545,15 @@ sealed abstract class List[+A] extends Seq[A] { */ override def last: A = if (isEmpty) throw new Predef.NoSuchElementException("Nil.last") - else if (tail.isEmpty) head - else tail.last + else { + var cur = this + var next = this.tail + while (!next.isEmpty) { + cur = next + next = next.tail + } + cur.head + } /** Returns the <code>n</code> first elements of this list, or else the whole * list, if it has less than <code>n</code> elements. @@ -580,9 +592,15 @@ sealed abstract class List[+A] extends Seq[A] { * @param n the number of elements to drop. * @return the list without its <code>n</code> first elements. */ - override def drop(n: Int): List[A] = - if (isEmpty || n <= 0) this - else (tail drop (n-1)) + override def drop(n: Int): List[A] = { + var these = this + var count = n + while (!these.isEmpty && count > 0) { + these = these.tail + count -= 1 + } + these + } /** Returns the rightmost <code>n</code> elements from this list. * diff --git a/src/library/scala/Responder.scala b/src/library/scala/Responder.scala index 9aade29aa1..fd7e5f1b35 100644 --- a/src/library/scala/Responder.scala +++ b/src/library/scala/Responder.scala @@ -12,6 +12,7 @@ package scala /** This object contains utility methods to build responders. * + * @author Martin Odersky * @author Burak Emir * @version 1.0 * @@ -60,6 +61,7 @@ object Responder { * Scala while giving the impression that programs in these DSLs are * written in direct style. * + * @author Martin Odersky * @author Burak Emir * @version 1.0 */ diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 015bda5f21..fafdf8e175 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -191,4 +191,8 @@ trait Map[A, +B] extends PartialFunction[A, B] with Collection[(A, B)] { override def contains(key : A) = Map.this.contains(key) override def get(key : A) = Map.this.get(key).map(f) } + + /** Defines the prefix of this object's <code>toString</code> representation. + */ + override protected def stringPrefix : String = "Map" } diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala index 4f412712d6..aac1342a37 100644 --- a/src/library/scala/collection/Set.scala +++ b/src/library/scala/collection/Set.scala @@ -124,4 +124,8 @@ trait Set[A] extends (A => Boolean) with Collection[A] { copyToArray(result, 0) result } + + /** Defines the prefix of this object's <code>toString</code> representation. + */ + override protected def stringPrefix : String = "Set" } diff --git a/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala b/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala index fc04116692..e278869f7a 100644 --- a/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala +++ b/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala @@ -37,9 +37,9 @@ class StdLexical extends Lexical with StdTokens { def token: Parser[Token] = ( letter ~ rep( letter | digit ) ^^ { case first ~ rest => processIdent(first :: rest mkString "") } | digit ~ rep( digit ) ^^ { case first ~ rest => NumericLit(first :: rest mkString "") } - | '\'' ~ rep( chrExcept('\'', '\n', EofCh) ) ~ '\'' ^^ { case _ ~ chars ~ _ => StringLit(chars mkString "") } - | '\"' ~ rep( chrExcept('\"', '\n', EofCh) ) ~ '\"' ^^ { case _ ~ chars ~ _ => StringLit(chars mkString "") } - | EofCh ^^ const(EOF) + | '\'' ~ rep( chrExcept('\'', '\n', EofCh) ) ~ '\'' ^^ { case '\'' ~ chars ~ '\'' => StringLit(chars mkString "") } + | '\"' ~ rep( chrExcept('\"', '\n', EofCh) ) ~ '\"' ^^ { case '\"' ~ chars ~ '\"' => StringLit(chars mkString "") } + | EofCh ^^^ EOF | '\'' ~> failure("unclosed string literal") | '\"' ~> failure("unclosed string literal") | delim @@ -70,7 +70,7 @@ class StdLexical extends Lexical with StdTokens { private var _delim: Parser[Token] = null protected def delim: Parser[Token] = { - if(_delim eq null) { // construct parser for delimiters by |'ing together the parsers for the individual delimiters, + if (_delim eq null) { // construct parser for delimiters by |'ing together the parsers for the individual delimiters, // starting with the longest one (hence the sort + reverse) -- otherwise a delimiter D will never be matched if // there is another delimiter that is a prefix of D def parseDelim(s: String): Parser[Token] = accept(s.toList) ^^ { x => Keyword(s) } diff --git a/test/files/neg/t0152.scala b/test/files/neg/t0152.scala new file mode 100755 index 0000000000..eef69bf767 --- /dev/null +++ b/test/files/neg/t0152.scala @@ -0,0 +1,13 @@ +class Value[+T](x: T) { + def value = x +} + +trait PlusOne extends Value[Int] { + override def value = super.value + 1 +} + +object Test extends Application { + object boom extends Value[java.lang.String]("foo") with PlusOne + + println(boom.value) // class cast exception! +} diff --git a/test/files/pos/listpattern.scala b/test/files/pos/listpattern.scala new file mode 100755 index 0000000000..47145bf037 --- /dev/null +++ b/test/files/pos/listpattern.scala @@ -0,0 +1,8 @@ +trait Value {} +case class FloatValue(x: Double) extends Value +object Test { + def applyNumeric(op: (Double, Double) => Double): + PartialFunction[List[Value], Value] = { + case List(FloatValue(x), FloatValue(y)) => FloatValue(op(x, y)) + } +} |