summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala20
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala36
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala51
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala18
-rw-r--r--src/library/scala/List.scala34
-rw-r--r--src/library/scala/Responder.scala2
-rw-r--r--src/library/scala/collection/Map.scala4
-rw-r--r--src/library/scala/collection/Set.scala4
-rw-r--r--src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala8
-rwxr-xr-xtest/files/neg/t0152.scala13
-rwxr-xr-xtest/files/pos/listpattern.scala8
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))
+ }
+}