diff options
-rw-r--r-- | src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/javac/JavaParsers.scala | 5 | ||||
-rw-r--r-- | src/library/scala/collection/generic/BitOperations.scala | 23 | ||||
-rw-r--r-- | src/library/scala/collection/parallel/Tasks.scala | 11 | ||||
-rw-r--r-- | src/library/scala/compat/Platform.scala | 3 | ||||
-rw-r--r-- | src/library/scala/math/Ordering.scala | 22 | ||||
-rw-r--r-- | src/library/scala/runtime/BoxesRunTime.java | 6 | ||||
-rw-r--r-- | src/library/scala/sys/process/BasicIO.scala | 2 | ||||
-rw-r--r-- | src/library/scala/util/Properties.scala | 2 | ||||
-rw-r--r-- | src/library/scala/util/control/NoStackTrace.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/SymbolTable.scala | 28 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala | 4 | ||||
-rw-r--r-- | test/files/pos/java-type-annotations/NotNull.java | 6 | ||||
-rw-r--r-- | test/files/pos/java-type-annotations/Test.java | 4 | ||||
-rw-r--r-- | test/files/run/t5375.check | 1 | ||||
-rw-r--r-- | test/files/run/t5375.scala | 16 |
16 files changed, 82 insertions, 67 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala index 5fd9c0db34..d4b8175d28 100644 --- a/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala +++ b/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala @@ -1,8 +1,12 @@ package scala.reflect.macros package runtime +import java.net.URLClassLoader + import scala.reflect.internal.Flags._ +import scala.reflect.internal.util.ScalaClassLoader import scala.reflect.runtime.ReflectionUtils +import scala.reflect.internal.util.AbstractFileClassLoader trait MacroRuntimes extends JavaReflectionRuntimes { self: scala.tools.nsc.typechecker.Analyzer => @@ -44,7 +48,15 @@ trait MacroRuntimes extends JavaReflectionRuntimes { * which compiles implementations into a virtual directory (very much like REPL does) and then conjures * a classloader mapped to that virtual directory. */ - lazy val defaultMacroClassloader: ClassLoader = findMacroClassLoader() + private lazy val defaultMacroClassloaderCache = { + def attemptClose(loader: ClassLoader): Unit = loader match { + case u: URLClassLoader => debuglog("Closing macro runtime classloader"); u.close() + case afcl: AbstractFileClassLoader => attemptClose(afcl.getParent) + case _ => ??? + } + perRunCaches.newGeneric(findMacroClassLoader, attemptClose _) + } + def defaultMacroClassloader: ClassLoader = defaultMacroClassloaderCache() /** Abstracts away resolution of macro runtimes. */ diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 8cdc5944e8..cc851b6330 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -264,7 +264,8 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { } } - def typ(): Tree = + def typ(): Tree = { + annotations() optArrayBrackets { if (in.token == FINAL) in.nextToken() if (in.token == IDENTIFIER) { @@ -287,6 +288,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { basicType() } } + } def typeArgs(t: Tree): Tree = { val wildcards = new ListBuffer[TypeDef] @@ -404,6 +406,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def typeParam(): TypeDef = atPos(in.currentPos) { + annotations() val name = identForType() val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else EmptyTree TypeDef(Modifiers(Flags.JAVA | Flags.DEFERRED | Flags.PARAM), name, Nil, TypeBoundsTree(EmptyTree, hi)) diff --git a/src/library/scala/collection/generic/BitOperations.scala b/src/library/scala/collection/generic/BitOperations.scala index d430ece2f5..2f460eee1f 100644 --- a/src/library/scala/collection/generic/BitOperations.scala +++ b/src/library/scala/collection/generic/BitOperations.scala @@ -26,16 +26,7 @@ private[collection] object BitOperations { def complement(i: Int) = (-1) ^ i def bits(num: Int) = 31 to 0 by -1 map (i => (num >>> i & 1) != 0) def bitString(num: Int, sep: String = "") = bits(num) map (b => if (b) "1" else "0") mkString sep - - def highestOneBit(j: Int) = { - var i = j - i |= (i >> 1) - i |= (i >> 2) - i |= (i >> 4) - i |= (i >> 8) - i |= (i >> 16) - i - (i >>> 1) - } + def highestOneBit(j: Int) = java.lang.Integer.highestOneBit(j) } object Int extends Int @@ -49,17 +40,7 @@ private[collection] object BitOperations { def complement(i: Long) = (-1L) ^ i def bits(num: Long) = 63L to 0L by -1L map (i => (num >>> i & 1L) != 0L) def bitString(num: Long, sep: String = "") = bits(num) map (b => if (b) "1" else "0") mkString sep - - def highestOneBit(j: Long) = { - var i = j - i |= (i >> 1) - i |= (i >> 2) - i |= (i >> 4) - i |= (i >> 8) - i |= (i >> 16) - i |= (i >> 32) - i - (i >>> 1) - } + def highestOneBit(j: Long) = java.lang.Long.highestOneBit(j) } object Long extends Long } diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index c9a75752df..2a4e40dd16 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -66,13 +66,10 @@ trait Task[R, +Tp] { } private[parallel] def mergeThrowables(that: Task[_, _]) { - // TODO: As soon as we target Java >= 7, use Throwable#addSuppressed - // to pass additional Throwables to the caller, e. g. - // if (this.throwable != null && that.throwable != null) - // this.throwable.addSuppressed(that.throwable) - // For now, we just use whatever Throwable comes across “first”. - if (this.throwable == null && that.throwable != null) - this.throwable = that.throwable + if (this.throwable != null && that.throwable != null) + this.throwable.addSuppressed(that.throwable) + else if (this.throwable == null && that.throwable != null) + this.throwable = that.throwable } // override in concrete task implementations to signal abort to other tasks diff --git a/src/library/scala/compat/Platform.scala b/src/library/scala/compat/Platform.scala index 42dfcbfdde..f3745bc189 100644 --- a/src/library/scala/compat/Platform.scala +++ b/src/library/scala/compat/Platform.scala @@ -105,8 +105,7 @@ object Platform { /** The default line separator. * * On the JVM, this is equivalent to calling the method: - * `System.getProperty("line.separator")` - * with a default value of "\n". + * `java.lang.System.lineSeparator` */ val EOL = scala.util.Properties.lineSeparator diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index 827cccc77e..37096d5ed0 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -224,42 +224,32 @@ object Ordering extends LowPriorityOrderingImplicits { implicit object Unit extends UnitOrdering trait BooleanOrdering extends Ordering[Boolean] { - def compare(x: Boolean, y: Boolean) = (x, y) match { - case (false, true) => -1 - case (true, false) => 1 - case _ => 0 - } + def compare(x: Boolean, y: Boolean) = java.lang.Boolean.compare(x, y) } implicit object Boolean extends BooleanOrdering trait ByteOrdering extends Ordering[Byte] { - def compare(x: Byte, y: Byte) = x.toInt - y.toInt + def compare(x: Byte, y: Byte) = java.lang.Byte.compare(x, y) } implicit object Byte extends ByteOrdering trait CharOrdering extends Ordering[Char] { - def compare(x: Char, y: Char) = x.toInt - y.toInt + def compare(x: Char, y: Char) = java.lang.Character.compare(x, y) } implicit object Char extends CharOrdering trait ShortOrdering extends Ordering[Short] { - def compare(x: Short, y: Short) = x.toInt - y.toInt + def compare(x: Short, y: Short) = java.lang.Short.compare(x, y) } implicit object Short extends ShortOrdering trait IntOrdering extends Ordering[Int] { - def compare(x: Int, y: Int) = - if (x < y) -1 - else if (x == y) 0 - else 1 + def compare(x: Int, y: Int) = java.lang.Integer.compare(x, y) } implicit object Int extends IntOrdering trait LongOrdering extends Ordering[Long] { - def compare(x: Long, y: Long) = - if (x < y) -1 - else if (x == y) 0 - else 1 + def compare(x: Long, y: Long) = java.lang.Long.compare(x, y) } implicit object Long extends LongOrdering diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 96e0f23f3d..9ae118f43f 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -236,10 +236,10 @@ public final class BoxesRunTime if (iv == dv) return iv; long lv = n.longValue(); - if (lv == dv) return java.lang.Long.valueOf(lv).hashCode(); + if (lv == dv) return java.lang.Long.hashCode(lv); float fv = n.floatValue(); - if (fv == dv) return java.lang.Float.valueOf(fv).hashCode(); + if (fv == dv) return java.lang.Float.hashCode(fv); else return n.hashCode(); } public static int hashFromFloat(java.lang.Float n) { @@ -248,7 +248,7 @@ public final class BoxesRunTime if (iv == fv) return iv; long lv = n.longValue(); - if (lv == fv) return java.lang.Long.valueOf(lv).hashCode(); + if (lv == fv) return java.lang.Long.hashCode(lv); else return n.hashCode(); } public static int hashFromNumber(java.lang.Number n) { diff --git a/src/library/scala/sys/process/BasicIO.scala b/src/library/scala/sys/process/BasicIO.scala index 640f7e68c2..b39ae77c62 100644 --- a/src/library/scala/sys/process/BasicIO.scala +++ b/src/library/scala/sys/process/BasicIO.scala @@ -33,7 +33,7 @@ object BasicIO { final val BufferSize = 8192 /** Used to separate lines in the `processFully` function that takes `Appendable`. */ - final val Newline = props("line.separator") + final val Newline = System.lineSeparator private[process] final class Streamed[T]( val process: T => Unit, diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index 583f1539d1..a176748cd6 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -120,7 +120,7 @@ private[scala] trait PropertiesTrait { /** The default end of line character. */ - def lineSeparator = propOrElse("line.separator", "\n") + def lineSeparator = System.lineSeparator() /* Various well-known properties. */ def javaClassPath = propOrEmpty("java.class.path") diff --git a/src/library/scala/util/control/NoStackTrace.scala b/src/library/scala/util/control/NoStackTrace.scala index 3c42944af1..3647af4ac3 100644 --- a/src/library/scala/util/control/NoStackTrace.scala +++ b/src/library/scala/util/control/NoStackTrace.scala @@ -14,6 +14,8 @@ package util.control * on a global basis via a system property wrapper in * [[scala.sys.SystemProperties]]. * + * @note Since JDK 1.7, a similar effect can be achieved with `class Ex extends Throwable(..., writableStackTrace = false)` + * * @author Paul Phillips * @since 2.8 */ diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 88a94ab530..6d988479af 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -375,20 +375,30 @@ abstract class SymbolTable extends macros.Universe def newWeakSet[K <: AnyRef]() = recordCache(new WeakHashSet[K]()) def newAnyRefMap[K <: AnyRef, V]() = recordCache(mutable.AnyRefMap[K, V]()) - def newGeneric[T](f: => T): () => T = { + /** + * Register a cache specified by a factory function and (optionally) a cleanup function. + * + * @return A function that will return cached value, or create a fresh value when a new run is started. + */ + def newGeneric[T](f: => T, cleanup: T => Unit = (x: Any) => ()): () => T = { val NoCached: T = null.asInstanceOf[T] var cached: T = NoCached var cachedRunId = NoRunId - recordCache(new Clearable { - def clear(): Unit = cached = NoCached - }) - () => { - if (currentRunId != cachedRunId || cached == NoCached) { - cached = f - cachedRunId = currentRunId + val clearable = new Clearable with (() => T) { + def clear(): Unit = { + if (cached != NoCached) + cleanup(cached) + cached = NoCached + } + def apply(): T = { + if (currentRunId != cachedRunId || cached == NoCached) { + cached = f + cachedRunId = currentRunId + } + cached } - cached } + recordCache(clearable) } } diff --git a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala index cc5be92489..f3db2017be 100644 --- a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala +++ b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala @@ -139,6 +139,10 @@ object ScalaClassLoader { classloaderURLs :+= url super.addURL(url) } + override def close(): Unit = { + super.close() + classloaderURLs = null + } } def fromURLs(urls: Seq[URL], parent: ClassLoader = null): URLClassLoader = diff --git a/test/files/pos/java-type-annotations/NotNull.java b/test/files/pos/java-type-annotations/NotNull.java new file mode 100644 index 0000000000..2716fe1a99 --- /dev/null +++ b/test/files/pos/java-type-annotations/NotNull.java @@ -0,0 +1,6 @@ +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +public @interface NotNull { +} diff --git a/test/files/pos/java-type-annotations/Test.java b/test/files/pos/java-type-annotations/Test.java new file mode 100644 index 0000000000..d6bda1dedb --- /dev/null +++ b/test/files/pos/java-type-annotations/Test.java @@ -0,0 +1,4 @@ +public class Test { + static class C<@NotNull T> {}; + @NotNull String foo() { return ""; } +} diff --git a/test/files/run/t5375.check b/test/files/run/t5375.check index b1a57eeeec..e69de29bb2 100644 --- a/test/files/run/t5375.check +++ b/test/files/run/t5375.check @@ -1 +0,0 @@ -Runtime exception diff --git a/test/files/run/t5375.scala b/test/files/run/t5375.scala index 826ecd841e..2028b6f05d 100644 --- a/test/files/run/t5375.scala +++ b/test/files/run/t5375.scala @@ -1,8 +1,16 @@ object Test extends App { val foos = (1 to 1000).toSeq - try - foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i) - catch { - case ex: RuntimeException => println("Runtime exception") + try { + foos.par.map(i => if (i % 37 == 0) throw new MultipleOf37Exception(i) else i) + assert(false) + } catch { + case ex: MultipleOf37Exception => + assert(ex.getSuppressed.size > 0) + assert(ex.getSuppressed.forall(_.isInstanceOf[MultipleOf37Exception])) + assert(ex.i == 37) + assert(ex.getSuppressed.map(_.asInstanceOf[MultipleOf37Exception].i).toList == List(74, 148, 259, 518)) + case _: Throwable => + assert(false) } + class MultipleOf37Exception(val i: Int) extends RuntimeException } |