From ec18f148e8afc4101878cd8b05eadac92d26b64c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 18 Aug 2009 17:24:36 +0000 Subject: Fixed memory leaks for streams. --- lib/scala-compiler.jar.desired.sha1 | 2 +- lib/scala-library-src.jar.desired.sha1 | 2 +- lib/scala-library.jar.desired.sha1 | 2 +- .../scala/tools/nsc/ast/parser/Parsers.scala | 73 ++++++++++++---------- .../scala/tools/nsc/ast/parser/TreeBuilder.scala | 13 ++-- .../scala/tools/nsc/typechecker/Implicits.scala | 13 ++-- .../scala/tools/nsc/typechecker/Typers.scala | 33 ++++++---- .../scala/collection/immutable/Stream.scala | 65 ++++++++----------- src/library/scala/reflect/Manifest.scala | 67 +++++++++++++++++++- src/library/scala/runtime/BoxedObjectArray.scala | 24 ------- test/files/jvm/manifests.check | 34 +++++----- test/files/neg/bug882.check | 2 +- test/files/neg/t1701.check | 4 ++ test/files/neg/t1701.scala | 1 + test/files/pos/exbound.scala | 7 +++ test/files/pos/implicits.scala | 32 ++++++++++ test/files/pos/t1614/bar.scala | 4 ++ test/files/pos/t1614/foo.scala | 12 ++++ 18 files changed, 250 insertions(+), 140 deletions(-) create mode 100644 test/files/neg/t1701.check create mode 100755 test/files/neg/t1701.scala create mode 100755 test/files/pos/exbound.scala create mode 100755 test/files/pos/implicits.scala create mode 100755 test/files/pos/t1614/bar.scala create mode 100755 test/files/pos/t1614/foo.scala diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index d3e09a06d8..d3bbd16629 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -3e2486ec3212ff87ab890bd351b1ecf91d316e01 ?scala-compiler.jar +972d3a12779e2cee43fc4f0085710f5a5f908479 ?scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index 5e1d669d71..fac8ce0f24 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -8d3165e028ec4d7418c49dcc188c192108214a01 ?scala-library-src.jar +874a57a6804e974f66aa71014d6823fb88e6a12a ?scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index d95a555370..b29dd577af 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -78395a28c554de8934411e42f99dbb23ff0dce44 ?scala-library.jar +065eca5c251e3750915ea6e8ea9409653a5e5490 ?scala-library.jar diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index bb0fa89b29..34338eaf03 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -166,8 +166,9 @@ self => } import treeBuilder.{global => _, _} - /** The implicit view parameters of the surrounding class */ - var implicitClassViews: List[Tree] = Nil + /** The types of the context bounds of type parameters of the surrounding class + */ + var classContextBounds: List[Tree] = Nil /** this is the general parse method */ @@ -1661,7 +1662,7 @@ self => * ClassParams ::= ClassParam {`,' ClassParam} * ClassParam ::= {Annotation} [{Modifier} (`val' | `var')] Id [`:' ParamType] [`=' Expr] */ - def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = { + def paramClauses(owner: Name, contextBounds: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = { var implicitmod = 0 var caseParam = ofCaseClass def param(): ValDef = { @@ -1715,8 +1716,8 @@ self => val params = new ListBuffer[ValDef] if (in.token != RPAREN) { if (in.token == IMPLICIT) { - if (!implicitViews.isEmpty) - syntaxError("cannot have both view bounds `<%' and implicit parameters", false) + if (!contextBounds.isEmpty) + syntaxError("cannot have both implicit parameters and context bounds `: ...' on type parameters", false) in.nextToken() implicitmod = Flags.IMPLICIT } @@ -1750,18 +1751,18 @@ self => incompleteInputError("auxiliary constructor needs non-implicit parameter list") else syntaxError(start, "auxiliary constructor needs non-implicit parameter list", false) - addImplicitViews(owner, result, implicitViews) + addEvidenceParams(owner, result, contextBounds) } /** ParamType ::= Type | `=>' Type | Type `*' */ def paramType(): Tree = - if (in.token == ARROW) + if (in.token == ARROW) { atPos(in.skipToken()) { AppliedTypeTree( rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ())) } - else { + } else { val t = typ() if (isIdent && in.name == STAR) { in.nextToken() @@ -1777,9 +1778,9 @@ self => * VariantTypeParam ::= {Annotation} [`+' | `-'] TypeParam * FunTypeParamClauseOpt ::= [FunTypeParamClause] * FunTypeParamClause ::= `[' TypeParam {`,' TypeParam} `]'] - * TypeParam ::= Id TypeParamClauseOpt TypeBounds [<% Type] + * TypeParam ::= Id TypeParamClauseOpt TypeBounds {<% Type} {":" Type} */ - def typeParamClauseOpt(owner: Name, implicitViewBuf: ListBuffer[Tree]): List[TypeDef] = { + def typeParamClauseOpt(owner: Name, contextBoundBuf: ListBuffer[Tree]): List[TypeDef] = { def typeParam(ms: Modifiers): TypeDef = { var mods = ms | Flags.PARAM val start = in.offset @@ -1799,16 +1800,21 @@ self => nme.WILDCARD } else ident()).toTypeName val param = atPos(start, nameOffset) { - val tparams = typeParamClauseOpt(pname, null) // @M TODO null --> no higher-order view bounds for now + val tparams = typeParamClauseOpt(pname, null) // @M TODO null --> no higher-order context bounds for now TypeDef(mods, pname, tparams, typeBounds()) } - if (in.token == VIEWBOUND && (implicitViewBuf ne null)) - implicitViewBuf += atPos(start, in.skipToken()) { - val t = typ() - atPos(t.pos) { - makeFunctionTypeTree(List(Ident(pname)), t) + if (contextBoundBuf ne null) { + while (in.token == VIEWBOUND) { + contextBoundBuf += atPos(in.skipToken()) { + makeFunctionTypeTree(List(Ident(pname)), typ()) } } + while (in.token == COLON) { + contextBoundBuf += atPos(in.skipToken()) { + AppliedTypeTree(typ(), List(Ident(pname))) + } + } + } param } val params = new ListBuffer[TypeDef] @@ -2050,7 +2056,7 @@ self => val start = in.skipToken() if (in.token == THIS) { atPos(start, in.skipToken()) { - val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (_.duplicate), false) + val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), false) newLineOptWhenFollowedBy(LBRACE) val rhs = if (in.token == LBRACE) { atPos(in.offset) { constrBlock(vparamss) } @@ -2065,11 +2071,12 @@ self => val nameOffset = in.offset val name = ident() atPos(start, if (name == nme.ERROR) start else nameOffset) { - // implicitViewBuf is for view bounded type parameters of the form - // [T <% B]; it contains the equivalent implicit parameter, i.e. (implicit p: T => B) - val implicitViewBuf = new ListBuffer[Tree] - val tparams = typeParamClauseOpt(name, implicitViewBuf) - val vparamss = paramClauses(name, implicitViewBuf.toList, false) + // contextBoundBuf is for context bounded type parameters of the form + // [T : B] or [T : => B]; it contains the equivalent implicit parameter type, + // i.e. (B[T] or T => B) + val contextBoundBuf = new ListBuffer[Tree] + val tparams = typeParamClauseOpt(name, contextBoundBuf) + val vparamss = paramClauses(name, contextBoundBuf.toList, false) newLineOptWhenFollowedBy(LBRACE) var restype = typedOpt() val rhs = @@ -2105,7 +2112,7 @@ self => t = Apply(t, argumentExprs()) newLineOptWhenFollowedBy(LBRACE) } - if (implicitClassViews.isEmpty) t + if (classContextBounds.isEmpty) t else Apply(t, vparamss.last.map(vp => Ident(vp.name))) } @@ -2183,19 +2190,19 @@ self => val nameOffset = in.offset val name = ident().toTypeName atPos(start, if (name == nme.ERROR.toTypeName) start else nameOffset) { - val savedViews = implicitClassViews - val implicitViewBuf = new ListBuffer[Tree] - val tparams = typeParamClauseOpt(name, implicitViewBuf) - implicitClassViews = implicitViewBuf.toList - val tstart = (in.offset::implicitClassViews.map(_.pos.startOrPoint)).min - if (!implicitClassViews.isEmpty && mods.hasFlag(Flags.TRAIT)) { - syntaxError("traits cannot have type parameters with <% bounds", false) - implicitClassViews = List() + val savedContextBounds = classContextBounds + val contextBoundBuf = new ListBuffer[Tree] + val tparams = typeParamClauseOpt(name, contextBoundBuf) + classContextBounds = contextBoundBuf.toList + val tstart = (in.offset::classContextBounds.map(_.pos.startOrPoint)).min + if (!classContextBounds.isEmpty && mods.hasFlag(Flags.TRAIT)) { + syntaxError("traits cannot have type parameters with context bounds `: ...'", false) + classContextBounds = List() } val constrAnnots = annotations(false, true) val (constrMods, vparamss) = if (mods.hasFlag(Flags.TRAIT)) (Modifiers(Flags.TRAIT), List()) - else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE))) + else (accessModifierOpt(), paramClauses(name, classContextBounds, mods.hasFlag(Flags.CASE))) var mods1 = mods if (mods hasFlag Flags.TRAIT) { if (settings.Xexperimental.value && in.token == SUBTYPE) mods1 |= Flags.DEFERRED @@ -2205,7 +2212,7 @@ self => val template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss, tstart) if (isInterface(mods1, template.body)) mods1 |= Flags.INTERFACE val result = ClassDef(mods1, name, tparams, template) - implicitClassViews = savedViews + classContextBounds = savedContextBounds result } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index a8ecf9aab3..aa057c43b5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -507,12 +507,13 @@ abstract class TreeBuilder { def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = AppliedTypeTree(rootScalaDot(newTypeName("Function" + argtpes.length)), argtpes ::: List(restpe)) - /** Append implicit view section if for `implicitViews' if nonempty */ - def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = { - val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM) - def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName("view$"), tpt, EmptyTree) - if (implicitViews.isEmpty) vparamss - else vparamss ::: List(implicitViews map makeViewParam) + /** Append implicit parameter section if `contextBounds' nonempty */ + def addEvidenceParams(owner: Name, vparamss: List[List[ValDef]], contextBounds: List[Tree]): List[List[ValDef]] = + if (contextBounds.isEmpty) vparamss + else { + val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM) + def makeEvidenceParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName("man$"), tpt, EmptyTree) + vparamss ::: List(contextBounds map makeEvidenceParam) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 9295ba261d..1fe8220dc2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -130,7 +130,7 @@ self: Analyzer => class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context) extends Typer(context0) { - assert(tree.isEmpty || tree.pos.isDefined) + assert(tree.isEmpty || tree.pos.isDefined, tree) import infer._ @@ -599,7 +599,7 @@ self: Analyzer => def manifestFactoryCall(constructor: String, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree else - typed(atPos(tree.pos.focus) { + typed { atPos(tree.pos.focus) { Apply( TypeApply( Select(gen.mkAttributedRef(ManifestModule), constructor), @@ -607,7 +607,7 @@ self: Analyzer => ), args.toList ) - }) + }} /** Re-wraps a type in a manifest before calling inferImplicit on the result */ def findManifest(tp: Type): Tree = @@ -619,7 +619,12 @@ self: Analyzer => case ConstantType(value) => findManifest(tp.deconst) case TypeRef(pre, sym, args) => - if (sym.isClass) { + if (isValueClass(sym)) { + typed { atPos(tree.pos.focus) { + Select(gen.mkAttributedRef(ManifestModule), sym.name.toString) + }} + } + else if (sym.isClass) { val suffix = gen.mkClassOf(tp) :: (args map findManifest) manifestFactoryCall( "classType", diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 94d3aae091..745d1c8241 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -301,7 +301,7 @@ trait Typers { self: Analyzer => case t => t } "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile." - } else "")) + } else "")) /** Would tree be a stable (i.e. a pure expression) if the type * of its symbol was not volatile? @@ -1265,7 +1265,11 @@ trait Typers { self: Analyzer => r } else { val rhs = gen.mkCheckInit(Select(This(value.owner), value)) - val r = DefDef(getter, typed(rhs, EXPRmode, value.tpe)) + val r = typed { + atPos(getter.pos.focus) { + DefDef(getter, rhs) + } + }.asInstanceOf[DefDef] r.tpt.setPos(tpt.pos.focus) r } @@ -1273,15 +1277,22 @@ trait Typers { self: Analyzer => checkNoEscaping.privates(getter, getterDef.tpt) def setterDef(setter: Symbol): DefDef = { setter.setAnnotations(value.annotations) - val result = atPos(vdef.pos.focus)( - DefDef(setter, - if ((mods hasFlag DEFERRED) || (setter hasFlag OVERLOADED)) - EmptyTree - else - typed(Assign(Select(This(value.owner), value), - Ident(setter.paramss.head.head))))) - treeCopy.DefDef(result, result.mods, result.name, result.tparams, - result.vparamss, result.tpt, result.rhs) + val result = typed { + atPos(vdef.pos.focus) { + DefDef( + setter, + if ((mods hasFlag DEFERRED) || (setter hasFlag OVERLOADED)) + EmptyTree + else + Assign(Select(This(value.owner), value), + Ident(setter.paramss.head.head))) + } + } + result.asInstanceOf[DefDef] + // Martin: was + // treeCopy.DefDef(result, result.mods, result.name, result.tparams, + // result.vparamss, result.tpt, result.rhs) + // but that's redundant, no? } val gs = new ListBuffer[DefDef] diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 856e8b2aa8..a00803797f 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -115,11 +115,9 @@ self => * we recognize that fact and optimize to get more laziness. */ override def ++[B >: A, That](that: Traversable[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { - def loop(these: Stream[A]): Stream[B] = - if (these.isEmpty) that.toStream else new Stream.Cons(these.head, loop(these.tail)) - loop(this).asInstanceOf[That] -// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] -// else super.++(that) + // we assume there is no other builder factory on streams and therefore know that That = Stream[A] + (if (isEmpty) that.toStream + else new Stream.Cons(head, (tail ++ that).asInstanceOf[Stream[A]])).asInstanceOf[That] } /** Create a new stream which contains all elements of this stream @@ -135,12 +133,9 @@ self => * @return f(a0), ..., f(an) if this * sequence is a0, ..., an. */ - override def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { - def loop(these: Stream[A]): Stream[B] = - if (these.isEmpty) Stream.Empty else new Stream.Cons(f(these.head), loop(these.tail)) - loop(this).asInstanceOf[That] -// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] -// else super.map(f) + override final def map[B, That](f: A => B)(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + (if (isEmpty) Stream.Empty + else new Stream.Cons(f(head), (tail map f).asInstanceOf[Stream[B]])).asInstanceOf[That] } /** Applies the given function f to each element of @@ -150,17 +145,17 @@ self => * @return f(a0) ::: ... ::: f(an) if * this stream is [a0, ..., an]. */ - override def flatMap[B, That](f: A => Traversable[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { - def loop(these: Stream[A]): Stream[B] = - if (these.isEmpty) Stream.Empty - else { - val seg = f(these.head) - if (seg.isEmpty) loop(these.tail) - else seg.toStream append loop(these.tail) - } - loop(this).asInstanceOf[That] -// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this).asInstanceOf[That] -// else super.flatMap(f) + override final def flatMap[B, That](f: A => Traversable[B])(implicit bf: BuilderFactory[B, That, Stream[A]]): That = { + // we assume there is no other builder factory on streams and therefore know that That = Stream[B] + // optimization: drop A's for which f yields no B + var rest = this + var seg: Traversable[B] = null + do { + if (rest.isEmpty) return Stream.Empty.asInstanceOf[That] + seg = f(rest.head) + rest = rest.tail + } while (seg.isEmpty) + (seg.toStream append (rest flatMap f).asInstanceOf[Stream[B]]).asInstanceOf[That] } /** Returns all the elements of this stream that satisfy the @@ -169,16 +164,11 @@ self => * @param p the predicate used to filter the stream. * @return the elements of this stream satisfying p. */ - override def filter(p: A => Boolean): Stream[A] = { - // drops A's for which p yields false - def loop(these: Stream[A]): Stream[A] = - if (these.isEmpty) Stream.Empty - else { - val b = p(these.head) - if (!b) loop(these.tail) - else new Stream.Cons(these.head, these.tail filter p) - } - loop(this) + override final def filter(p: A => Boolean): Stream[A] = { + // optimization: drop leading prefix of elems for which f returns false + var rest = this dropWhile (!p(_)) + if (rest.isEmpty) Stream.Empty + else new Stream.Cons(rest.head, rest.tail filter p) } /** Returns all the elements of this stream that satisfy the @@ -199,13 +189,10 @@ self => * Stream(a0, ..., am) * zip Stream(b0, ..., bn) is invoked. */ - override def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, Stream[A]]): That = { - def loop(these: Stream[A], elems2: Iterator[B]): Stream[(A1, B)] = - if (these.isEmpty || !elems2.hasNext) Stream.Empty - else new Stream.Cons((these.head, elems2.next), loop(these.tail, elems2)) - loop(this, that.iterator).asInstanceOf[That] -// was: if (bf.isInstanceOf[Stream.StreamBuilderFactory[_]]) loop(this, that.iterator).asInstanceOf[That] -// else super.zip[A1, B, That](that) + override final def zip[A1 >: A, B, That](that: Sequence[B])(implicit bf: BuilderFactory[(A1, B), That, Stream[A]]): That = { + // we assume there is no other builder factory on streams and therefore know that That = Stream[(A1, B)] + (if (this.isEmpty || that.isEmpty) Stream.Empty + else new Stream.Cons((this.head, that.head), (this.tail zip that.tail).asInstanceOf[Stream[(A1, B)]])).asInstanceOf[That] } /** Zips this iterable with its indices. `s.zipWithIndex` is equivalent to diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 94283b6e19..f5c9818b8d 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -11,6 +11,8 @@ package scala.reflect +import scala.runtime._ + /**

* A Manifest[T] is an opaque descriptor for type T. * Currently, its only use is to give access to the erasure of the type as a @@ -60,6 +62,12 @@ trait Manifest[T] extends OptManifest[T] { case _ => false } + def newArray(len: Int): BoxedArray[T] = { + // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests + new BoxedObjectArray(java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[AnyRef]]) + .asInstanceOf[BoxedArray[T]] + } + private[reflect] def typeArguments: Option[List[Manifest[_]]] = None } @@ -76,6 +84,60 @@ trait Manifest[T] extends OptManifest[T] { */ object Manifest { + val Byte = new (Manifest[Byte] @serializable) { + def erasure = java.lang.Byte.TYPE + override def toString = "Byte" + override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len)) + } + + val Short = new (Manifest[Short] @serializable) { + def erasure = java.lang.Short.TYPE + override def toString = "Short" + override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len)) + } + + val Char = new (Manifest[Char] @serializable) { + def erasure = java.lang.Character.TYPE + override def toString = "Char" + override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len)) + } + + val Int = new (Manifest[Int] @serializable) { + def erasure = java.lang.Integer.TYPE + override def toString = "Int" + override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len)) + } + + val Long = new (Manifest[Long] @serializable) { + def erasure = java.lang.Long.TYPE + override def toString = "Long" + override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len)) + } + + val Float = new (Manifest[Float] @serializable) { + def erasure = java.lang.Float.TYPE + override def toString = "Float" + override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len)) + } + + val Double = new (Manifest[Double] @serializable) { + def erasure = java.lang.Double.TYPE + override def toString = "Double" + override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len)) + } + + val Boolean = new (Manifest[Boolean] @serializable) { + def erasure = java.lang.Boolean.TYPE + override def toString = "Boolean" + override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len)) + } + + val Unit = new (Manifest[Unit] @serializable) { + def erasure = java.lang.Void.TYPE + override def toString = "Unit" + override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len)) + } + /** Manifest for the singleton type `value.type'. */ def singleType[T](value: Any): Manifest[T] = new (Manifest[T] @serializable) { @@ -92,6 +154,7 @@ object Manifest { def classType[T](clazz: Predef.Class[T]): Manifest[T] = new (Manifest[T] @serializable) { val erasure = clazz + // Martin why is toString a lazy val instead of a def? override lazy val toString = erasure.getName } @@ -104,7 +167,7 @@ object Manifest { override def <:<(that: Manifest[_]): Boolean = { that.typeArguments match { case Some(thatArgs) => - super.<:<(that) && args.equalsWith(thatArgs) { (x, y) => x <:< y } + super.<:<(that) && ((args zip thatArgs) forall { case (x, y) => x <:< y }) case None => false } @@ -151,7 +214,7 @@ object Manifest { /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = new (Manifest[T] @serializable) { - lazy val erasure = parents.first.erasure + lazy val erasure = parents.head.erasure override lazy val toString = parents.mkString(" with ") } diff --git a/src/library/scala/runtime/BoxedObjectArray.scala b/src/library/scala/runtime/BoxedObjectArray.scala index c46e54fd81..e19388e1b7 100644 --- a/src/library/scala/runtime/BoxedObjectArray.scala +++ b/src/library/scala/runtime/BoxedObjectArray.scala @@ -11,9 +11,7 @@ package scala.runtime - import Predef._ -import compat.Platform.createArray @serializable final class BoxedObjectArray[A <: AnyRef](val value: Array[AnyRef]) extends BoxedArray[A] { @@ -26,7 +24,6 @@ final class BoxedObjectArray[A <: AnyRef](val value: Array[AnyRef]) extends Boxe value(index) = elem } - def unbox(elemTag: String): AnyRef = value def unbox(elemClass: Class[_]): AnyRef = value /* @@ -37,26 +34,5 @@ final class BoxedObjectArray[A <: AnyRef](val value: Array[AnyRef]) extends Boxe override def hashCode(): Int = (value.asInstanceOf[AnyRef]).hashCode() */ - private def create(length: Int): Array[AnyRef] = { - createArray(value.getClass().getComponentType(), length).asInstanceOf[Array[AnyRef]] - } - - final override def filter(p: A => Boolean): BoxedArray[A] = { - val include = new Array[Boolean](value.length) - var len = 0 - var i = 0 - while (i < value.length) { - if (p(value(i).asInstanceOf[A])) { include(i) = true; len += 1 } - i += 1 - } - val result = create(len) - len = 0 - i = 0 - while (len < result.length) { - if (include(i)) { result(len) = value(i); len += 1 } - i += 1 - } - new BoxedObjectArray[A](result) - } } diff --git a/test/files/jvm/manifests.check b/test/files/jvm/manifests.check index f8ef5b203c..5a11ef3926 100644 --- a/test/files/jvm/manifests.check +++ b/test/files/jvm/manifests.check @@ -1,35 +1,35 @@ -x=(), m=void -x=true, m=boolean -x=a, m=char -x=1, m=int +x=(), m=Unit +x=true, m=Boolean +x=a, m=Char +x=1, m=Int x=abc, m=java.lang.String x='abc, m=scala.Symbol -x=List(()), m=scala.collection.immutable.List[void] -x=List(true), m=scala.collection.immutable.List[boolean] -x=List(1), m=scala.collection.immutable.List[int] +x=List(()), m=scala.collection.immutable.List[Unit] +x=List(true), m=scala.collection.immutable.List[Boolean] +x=List(1), m=scala.collection.immutable.List[Int] x=List(abc), m=scala.collection.immutable.List[java.lang.String] x=List('abc), m=scala.collection.immutable.List[scala.Symbol] -x=[Z, m=Array[boolean] -x=[C, m=Array[char] -x=[I, m=Array[int] +x=[Z, m=Array[Boolean] +x=[C, m=Array[Char] +x=[I, m=Array[Int] x=Array(abc), m=Array[java.lang.String] x=Array('abc), m=Array[scala.Symbol] -x=((),()), m=scala.Tuple2[void, void] -x=(true,false), m=scala.Tuple2[boolean, boolean] -x=(1,2), m=scala.Tuple2[int, int] +x=((),()), m=scala.Tuple2[Unit, Unit] +x=(true,false), m=scala.Tuple2[Boolean, Boolean] +x=(1,2), m=scala.Tuple2[Int, Int] x=(abc,xyz), m=scala.Tuple2[java.lang.String, java.lang.String] x=('abc,'xyz), m=scala.Tuple2[scala.Symbol, scala.Symbol] x=Test$, m=Test$ x=scala.collection.immutable.List$, m=scala.collection.immutable.List$ -x=Foo, m=Foo[int] -x=Foo, m=Foo[scala.collection.immutable.List[int]] -x=Foo, m=Foo[Foo[int]] -x=Foo, m=Foo[scala.collection.immutable.List[Foo[int]]] +x=Foo, m=Foo[Int] +x=Foo, m=Foo[scala.collection.immutable.List[Int]] +x=Foo, m=Foo[Foo[Int]] +x=Foo, m=Foo[scala.collection.immutable.List[Foo[Int]]] x=Test1$$anon$1, m=Test1$$anon$1 diff --git a/test/files/neg/bug882.check b/test/files/neg/bug882.check index 52245eb3b7..8f47fefd9b 100644 --- a/test/files/neg/bug882.check +++ b/test/files/neg/bug882.check @@ -1,4 +1,4 @@ -bug882.scala:2: error: traits cannot have type parameters with <% bounds +bug882.scala:2: error: traits cannot have type parameters with context bounds `: ...' trait SortedSet[A <% Ordered[A]] { ^ one error found diff --git a/test/files/neg/t1701.check b/test/files/neg/t1701.check new file mode 100644 index 0000000000..782b690bf0 --- /dev/null +++ b/test/files/neg/t1701.check @@ -0,0 +1,4 @@ +t1701.scala:1: error: java.lang.Cloneable does not take type parameters +class A extends java.lang.Cloneable[String, Option, Int] + ^ +one error found diff --git a/test/files/neg/t1701.scala b/test/files/neg/t1701.scala new file mode 100755 index 0000000000..7cd6ff9953 --- /dev/null +++ b/test/files/neg/t1701.scala @@ -0,0 +1 @@ +class A extends java.lang.Cloneable[String, Option, Int] diff --git a/test/files/pos/exbound.scala b/test/files/pos/exbound.scala new file mode 100755 index 0000000000..243d5832ce --- /dev/null +++ b/test/files/pos/exbound.scala @@ -0,0 +1,7 @@ +class A[T <: A[T]] { + +} + +object Test { + val x: A[X] forSome { type X } = null +} diff --git a/test/files/pos/implicits.scala b/test/files/pos/implicits.scala new file mode 100755 index 0000000000..88632850fa --- /dev/null +++ b/test/files/pos/implicits.scala @@ -0,0 +1,32 @@ +// #1579 +object Test1579 { + class Column + class Query[E](val value: E) + class Invoker(q: Any) { val foo = null } + + implicit def unwrap[C](q: Query[C]) = q.value + implicit def invoker(q: Query[Column]) = new Invoker(q) + + val q = new Query(new Column) + q.foo +} +// #1625 +object Test1625 { + + class Wrapped(x:Any) { + def unwrap() = x + } + + implicit def byName[A](x: =>A) = new Wrapped(x) + + implicit def byVal[A](x: A) = x + + def main(args: Array[String]) = { + +// val res:Wrapped = 7 // works + + val res = 7.unwrap() // doesn't work + + println("=> result: " + res) + } +} diff --git a/test/files/pos/t1614/bar.scala b/test/files/pos/t1614/bar.scala new file mode 100755 index 0000000000..be994c3af3 --- /dev/null +++ b/test/files/pos/t1614/bar.scala @@ -0,0 +1,4 @@ +// bar.scala +object Bar { + val a = new FooImpl with AbstractOverrideFoo +} diff --git a/test/files/pos/t1614/foo.scala b/test/files/pos/t1614/foo.scala new file mode 100755 index 0000000000..e6cc41bafd --- /dev/null +++ b/test/files/pos/t1614/foo.scala @@ -0,0 +1,12 @@ +// foo.scala +trait Foo { + def foo(arg: List[_]) +} +trait FooImpl extends Foo { + def foo(arg: List[_]) {} +} +trait AbstractOverrideFoo extends Foo { + abstract override def foo(arg: List[_]) { + super.foo(arg) + } +} -- cgit v1.2.3