Skip to content

Commit

Permalink
Merge pull request #8166 from adriaanm/merge-2.12.x-almost-summer
Browse files Browse the repository at this point in the history
Merge 2.12.x into 2.13.x [ci: last-only]
  • Loading branch information
retronym committed Jun 20, 2019
2 parents 9fe2c17 + 76ff4cd commit ec46ff8
Show file tree
Hide file tree
Showing 37 changed files with 930 additions and 263 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ lazy val junit = project.in(file("test") / "junit")
(forkOptions in Test) := (forkOptions in Test).value.withWorkingDirectory((baseDirectory in ThisBuild).value),
(forkOptions in Test in testOnly) := (forkOptions in Test in testOnly).value.withWorkingDirectory((baseDirectory in ThisBuild).value),
scalacOptions += "-feature",
libraryDependencies ++= Seq(junitInterfaceDep, jolDep),
libraryDependencies ++= Seq(junitInterfaceDep, jolDep, diffUtilsDep),
testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"),
unmanagedSourceDirectories in Compile := Nil,
unmanagedSourceDirectories in Test := List(baseDirectory.value)
Expand Down
13 changes: 8 additions & 5 deletions src/compiler/scala/tools/nsc/CompilerCommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

package scala.tools.nsc

import java.nio.file.Files

import io.File

/** A class representing command line info for scalac */
Expand Down Expand Up @@ -130,11 +132,12 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
*/
def expandArg(arg: String): List[String] = {
def stripComment(s: String) = s takeWhile (_ != '#')
val file = File(arg stripPrefix "@")
if (!file.exists)
throw new java.io.FileNotFoundException("argument file %s could not be found" format file.name)

settings splitParams (file.lines() map stripComment mkString " ")
import java.nio.file._
import collection.JavaConverters._
val file = Paths.get(arg stripPrefix "@")
if (!Files.exists(file))
throw new java.io.FileNotFoundException("argument file %s could not be found" format file)
settings splitParams (Files.readAllLines(file).asScala map stripComment mkString " ")
}

// override this if you don't want arguments processed here
Expand Down
280 changes: 200 additions & 80 deletions src/compiler/scala/tools/nsc/PipelineMain.scala

Large diffs are not rendered by default.

20 changes: 16 additions & 4 deletions src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ abstract class TreeBrowsers {
case _ =>
str.append("tree.id: ").append(t.id)
str.append("\ntree.pos: ").append(t.pos)
str.append(TreeInfo.attachments(t, "tree"))
str.append("\nSymbol: ").append(TreeInfo.symbolText(t))
str.append("\nSymbol owner: ").append(
if ((t.symbol ne null) && t.symbol != NoSymbol)
Expand Down Expand Up @@ -523,13 +524,24 @@ abstract class TreeBrowsers {
val s = t.symbol

if ((s ne null) && (s != NoSymbol)) {
var str = s.flagString
if (s.isStaticMember) str = str + " isStatic "
(str + " annotations: " + s.annotations.mkString("", " ", "")
+ (if (s.isTypeSkolem) "\ndeSkolemized annotations: " + s.deSkolemize.annotations.mkString("", " ", "") else ""))
val str = new StringBuilder(s.flagString)
if (s.isStaticMember) str ++= " isStatic "
str ++= " annotations: "
str ++= s.annotations.mkString("", " ", "")
if (s.isTypeSkolem) {
str ++= "\ndeSkolemized annotations: "
str ++= s.deSkolemize.annotations.mkString("", " ", "")
}
str ++= attachments(s, "")
str.toString
}
else ""
}

def attachments(t: Attachable, pre: String): String = {
if (t.attachments.isEmpty) ""
else t.attachments.all.mkString(s"\n$pre attachments:\n ","\n ","")
}
}

object TypePrinter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,35 +202,49 @@ final class FileBasedCache[T] {
private case class Stamp(lastModified: FileTime, size: Long, fileKey: Object)
private case class Entry(stamps: Seq[Stamp], t: T) {
val referenceCount: AtomicInteger = new AtomicInteger(1)
var timerTask: TimerTask = null
def cancelTimer(): Unit = {
timerTask match {
case null =>
case t => t.cancel()
}
}
}
private val cache = collection.mutable.Map.empty[Seq[Path], Entry]

private def referenceCountDecrementer(e: Entry, paths: Seq[Path]): Closeable = new Closeable {
var closed = false
override def close(): Unit = {
if (!closed) {
closed = true
val count = e.referenceCount.decrementAndGet()
if (count == 0) {
e.t match {
case cl: Closeable =>
FileBasedCache.timer match {
case Some(timer) =>
val task = new TimerTask {
override def run(): Unit = {
cache.synchronized {
if (e.referenceCount.compareAndSet(0, -1)) {
cache.remove(paths)
cl.close()
private def referenceCountDecrementer(e: Entry, paths: Seq[Path]): Closeable = {
// Cancel the deferred close timer (if any) that was started when the reference count
// last dropped to zero.
e.cancelTimer()

new Closeable {
var closed = false
override def close(): Unit = {
if (!closed) {
closed = true
val count = e.referenceCount.decrementAndGet()
if (count == 0) {
e.t match {
case cl: Closeable =>
FileBasedCache.timer match {
case Some(timer) =>
val task = new TimerTask {
override def run(): Unit = {
cache.synchronized {
if (e.referenceCount.compareAndSet(0, -1)) {
cache.remove(paths)
cl.close()
}
}
}
}
}
timer.schedule(task, FileBasedCache.deferCloseMs.toLong)
case None =>
cl.close()
}
case _ =>
e.timerTask = task
timer.schedule(task, FileBasedCache.deferCloseMs.toLong)
case None =>
cl.close()
}
case _ =>
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/plugins/Plugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ abstract class Plugin {
true
}

@deprecated("use Plugin#init instead", since="2.11.0")
@deprecatedOverriding("use Plugin#init instead", since="2.11.0")
def processOptions(options: List[String], error: String => Unit): Unit = {
if (!options.isEmpty) error(s"Error: $name takes no options")
}
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ trait ScalaSettings extends AbsScalaSettings
val YcacheMacroClassLoader = CachePolicy.setting("macro", "macros")
val YmacroClasspath = PathSetting ("-Ymacro-classpath", "The classpath used to reflectively load macro implementations, default is the compilation classpath.", "")

val Youtline = BooleanSetting ("-Youtline", "Don't compile method bodies. Use together with `-Ystop-afer:pickler to generate the pickled signatures for all source files.").internalOnly()

val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")

Expand Down Expand Up @@ -360,10 +362,10 @@ trait ScalaSettings extends AbsScalaSettings
| <sources> Classes defined in source files compiled in the current compilation, either
| passed explicitly to the compiler or picked up from the `-sourcepath`
|
|The setting accepts a list of patterns: `-opt-inline-from:p1:p2`. The setting can be passed
|The setting accepts a list of patterns: `-opt-inline-from:p1,p2`. The setting can be passed
|multiple times, the list of patterns gets extended. A leading `!` marks a pattern excluding.
|The last matching pattern defines whether a classfile is included or excluded (default: excluded).
|For example, `a.**:!a.b.**` includes classes in a and sub-packages, but not in a.b and sub-packages.
|For example, `a.**,!a.b.**` includes classes in a and sub-packages, but not in a.b and sub-packages.
|
|Note: on the command-line you might need to quote patterns containing `*` to prevent the shell
|from expanding it to a list of files in the current directory.""".stripMargin))
Expand Down
37 changes: 24 additions & 13 deletions src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1165,15 +1165,25 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (MethodType(params1, res1), MethodType(params2, res2)) =>
if (strict && params1.length != params2.length) unifyError(tp1, tp2)
debuglog(s"Unify methods $tp1 and $tp2")
unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict)
val env1 = unifyAux(res1, res2, env, strict)
if (params1.isEmpty) env1
else
foldLeft2(params1, params2)(env1){ (e, p1, p2) => unifyAux(p1.tpe, p2.tpe, e, strict) }
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
debuglog(s"Unify polytypes $tp1 and $tp2")
if (strict && tparams1.length != tparams2.length)
unifyError(tp1, tp2)
else if (tparams && tparams1.sizeCompare(tparams2) == 0)
unify(res1 :: tparams1.map(_.info), res2 :: tparams2.map(_.info), env, strict)
else if (tparams && tparams1.sizeCompare(tparams2) == 0) {
val env1 = unifyAux(res1, res2, env, strict)
if (tparams1.isEmpty) env1
else
foldLeft2(tparams1, tparams2)(env1){ (e, tp1, tp2) => unifyAux(tp1.info, tp2.info, e, strict) }
}
else
unify(res1, res2, env, strict)
case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) =>
val env1 = unifyAux(lo1, lo2, env, strict)
unifyAux(hi1, hi2, env1, strict)
case (PolyType(_, res), other) => unify(res, other, env, strict)
case (ThisType(_), ThisType(_)) => env
case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
Expand All @@ -1183,26 +1193,27 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (RefinedType(_, _), RefinedType(_, _)) => env
case (AnnotatedType(_, tp1), tp2) => unify(tp2, tp1, env, strict)
case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => unify(List(lo1, hi1), List(lo2, hi2), env, strict)
case _ =>
debuglog(s"don't know how to unify $tp1 [${tp1.getClass}] with $tp2 [${tp2.getClass}]")
env
}

private def unify(tp1: List[Type], tp2: List[Type], env: TypeEnv, strict: Boolean): TypeEnv = {
private def unify(tp1: List[Type], tp2: List[Type], env: TypeEnv, strict: Boolean): TypeEnv =
if (tp1.isEmpty || tp2.isEmpty) env
else foldLeft2(tp1, tp2)(env) { (env, arg1, arg2) =>
if (!strict) unify(arg1, arg2, env, strict)
unifyAux(arg1, arg2, env, strict)
}

private def unifyAux(arg1: Type, arg2: Type, env: TypeEnv, strict: Boolean): TypeEnv =
if (!strict) unify(arg1, arg2, env, strict)
else {
val nenv = unify(arg1, arg2, emptyEnv, strict)
if (env.keySet.intersect(nenv.keySet).isEmpty) env ++ nenv
else {
val nenv = unify(arg1, arg2, emptyEnv, strict)
if (env.keySet.intersect(nenv.keySet).isEmpty) env ++ nenv
else {
debuglog(s"could not unify: u($arg1, $arg2) yields $nenv, env: $env")
unifyError(tp1, tp2)
}
debuglog(s"could not unify: u($arg1, $arg2) yields $nenv, env: $env")
unifyError(arg1, arg2)
}
}
}

/** Apply the type environment 'env' to the given type. All type
* bindings are supposed to be to primitive types. A type variable
Expand Down
12 changes: 7 additions & 5 deletions src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,13 @@ trait Analyzer extends AnyRef
try {
val typer = newTyper(rootContext(unit))
unit.body = typer.typed(unit.body)
for (workItem <- unit.toCheck) workItem()
if (settings.warnUnusedImport)
warnUnusedImports(unit)
if (settings.warnUnused.isSetByUser)
new checkUnused(typer).apply(unit)
if (!settings.Youtline.value) {
for (workItem <- unit.toCheck) workItem()
if (settings.warnUnusedImport)
warnUnusedImports(unit)
if (settings.warnUnused.isSetByUser)
new checkUnused(typer).apply(unit)
}
}
finally {
unit.toCheck.clear()
Expand Down
12 changes: 10 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Namers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,11 @@ trait Namers extends MethodSynthesis {

val resTpGiven =
if (tpt.isEmpty) WildcardType
else typer.typedType(tpt).tpe
else {
val tptTyped = typer.typedType(tpt)
context.unit.transformed(tpt) = tptTyped
tptTyped.tpe
}


// ignore missing types unless we can look to overridden method to recover the missing information
Expand Down Expand Up @@ -1720,7 +1724,11 @@ trait Namers extends MethodSynthesis {

tptFromRhsUnderPt
}
} else typer.typedType(tpt).tpe
} else {
val tptTyped = typer.typedType(tpt)
context.unit.transformed(tpt) = tptTyped
tptTyped.tpe
}

// println(s"val: $result / ${vdef.tpt.tpe} / ")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ trait TypeDiagnostics {
}

if (t.tpe ne null) {
for (tp <- t.tpe if !treeTypes(tp)) {
for (tp <- t.tpe) if (!treeTypes(tp)) {
// Include references to private/local aliases (which might otherwise refer to an enclosing class)
val isAlias = {
val td = tp.typeSymbolDirect
Expand Down
16 changes: 12 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2115,7 +2115,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
sym.annotations.map(_.completeInfo())
sym.filterAnnotations(_ != UnmappableAnnotation)

val tpt1 = checkNoEscaping.privates(this, sym, typedType(vdef.tpt))
val tpt1 = checkNoEscaping.privates(this, sym, transformedOr(vdef.tpt, typedType(vdef.tpt)))
checkNonCyclic(vdef, tpt1)

// allow trait accessors: it's the only vehicle we have to hang on to annotations that must be passed down to
Expand Down Expand Up @@ -2348,7 +2348,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (isRepeatedParamType(vparam1.symbol.tpe))
StarParamNotLastError(vparam1)

val tpt1 = checkNoEscaping.privates(this, meth, typedType(ddef.tpt))
val tpt1 = checkNoEscaping.privates(this, meth, transformedOr(ddef.tpt, typedType(ddef.tpt)))
checkNonCyclic(ddef, tpt1)
ddef.tpt.setType(tpt1.tpe)
val typedMods = typedModifiers(ddef.mods)
Expand Down Expand Up @@ -6119,14 +6119,21 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
final def transformedOrTyped(tree: Tree, mode: Mode, pt: Type): Tree = {
lookupTransformed(tree) match {
case Some(tree1) => tree1
case _ => typed(tree, mode, pt)
case _ => if (canSkipRhs(tree)) EmptyTree else typed(tree, mode, pt)
}
}
final def lookupTransformed(tree: Tree): Option[Tree] =
if (phase.erasedTypes) None // OPT save the hashmap lookup in erasure type and beyond
else transformed remove tree
}

private final def canSkipRhs(tree: Tree) = settings.Youtline.value && !tree.exists {
case Super(qual, mix) =>
// conservative approximation of method bodies that may give rise to super accessors which must be
// stored in pickle.
context.owner.enclClass.isTrait || mix != tpnme.EMPTY
case _ => false
}
}

/** Finish computation of param aliases after typechecking is completed */
final def finishComputeParamAlias(): Unit = {
Expand Down Expand Up @@ -6155,6 +6162,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
superConstructorCalls.clear()
}

}

trait TypersStats {
Expand Down
3 changes: 2 additions & 1 deletion src/library/scala/concurrent/Awaitable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ trait Awaitable[+T] {
* @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
* @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[Exception])
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
def result(atMost: Duration)(implicit permit: CanAwait): T
}

Expand Down
3 changes: 2 additions & 1 deletion src/library/scala/concurrent/Future.scala
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ object Future {
throw new TimeoutException(s"Future timed out after [$atMost]")
}

@throws[Exception]
@throws[TimeoutException]
@throws[InterruptedException]
override final def result(atMost: Duration)(implicit permit: CanAwait): Nothing = {
ready(atMost)
throw new TimeoutException(s"Future timed out after [$atMost]")
Expand Down
3 changes: 2 additions & 1 deletion src/library/scala/concurrent/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ package concurrent {
* @throws TimeoutException if after waiting for the specified time `awaitable` is still not ready
* @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[Exception])
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
final def result[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable match {
case f: Future[T] if f.isCompleted => f.result(atMost)(AwaitPermission)
case _ => blocking(awaitable.result(atMost)(AwaitPermission))
Expand Down
2 changes: 1 addition & 1 deletion src/library/scala/deprecated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ import scala.annotation.meta._
* @see [[scala.deprecatedOverriding]]
* @see [[scala.deprecatedName]]
*/
@getter @setter @beanGetter @beanSetter
@getter @setter @beanGetter @beanSetter @field
@deprecatedInheritance("Scheduled for being final in 2.14", "2.13.0")
class deprecated(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation

0 comments on commit ec46ff8

Please sign in to comment.