Avoid CCE when scalac internally uses compileLate. Fixes #2452

For example, when the `--sourcepath` option is provided
and the refchecks phase compiles an annotation found
on a referenced symbol from the sourcepath.

`compileLate` assumes that all non-sentinel compiler
phases can be down cast to `GlobalPhase`.

This commit changes the two phases in SBT to extend
this instead of `Phase`. This has the knock on benefit
of simplifying the phases by letting the `GlobalPhase.run`
iterator over the list of compilation units and feed them
to us one by one.

I checked that the test case failed before making each
change.
This commit is contained in:
Jason Zaugg 2016-02-10 22:48:10 +10:00 committed by Eugene Yokota
parent d3962a01ff
commit 7d4890b68a
7 changed files with 40 additions and 9 deletions

View File

@ -22,16 +22,19 @@ final class API(val global: CallbackGlobal) extends Compat {
@inline def debug(msg: => String) = if (settings.verbose.value) inform(msg)
def newPhase(prev: Phase) = new ApiPhase(prev)
class ApiPhase(prev: Phase) extends Phase(prev) {
class ApiPhase(prev: Phase) extends GlobalPhase(prev) {
override def description = "Extracts the public API from source files."
def name = API.name
def run: Unit =
override def run(): Unit =
{
val start = System.currentTimeMillis
currentRun.units.foreach(processUnit)
super.run
val stop = System.currentTimeMillis
debug("API phase took : " + ((stop - start) / 1000.0) + " s")
}
def apply(unit: global.CompilationUnit): Unit = processUnit(unit)
def processUnit(unit: CompilationUnit) = if (!unit.isJava) processScalaUnit(unit)
def processScalaUnit(unit: CompilationUnit): Unit = {
val sourceFile = unit.source.file.file

View File

@ -19,11 +19,11 @@ final class Analyzer(val global: CallbackGlobal) extends LocateClassFile {
import global._
def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev)
private class AnalyzerPhase(prev: Phase) extends Phase(prev) {
private class AnalyzerPhase(prev: Phase) extends GlobalPhase(prev) {
override def description = "Finds concrete instances of provided superclasses, and application entry points."
def name = Analyzer.name
def run {
for (unit <- currentRun.units if !unit.isJava) {
def apply(unit: CompilationUnit) {
if (!unit.isJava) {
val sourceFile = unit.source.file.file
// build list of generated classes
for (iclass <- unit.icode) {

View File

@ -33,11 +33,11 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile {
import global._
def newPhase(prev: Phase): Phase = new DependencyPhase(prev)
private class DependencyPhase(prev: Phase) extends Phase(prev) {
private class DependencyPhase(prev: Phase) extends GlobalPhase(prev) {
override def description = "Extracts dependency information"
def name = Dependency.name
def run: Unit = {
for (unit <- currentRun.units if !unit.isJava) {
def apply(unit: CompilationUnit): Unit = {
if (!unit.isJava) {
// build dependencies structure
val sourceFile = unit.source.file.file
if (global.callback.nameHashing) {

View File

@ -0,0 +1,5 @@
scalaVersion := "2.11.7"
scalacOptions in Compile ++= "-sourcepath" :: (baseDirectory.value / "srcpath").toString :: Nil

View File

@ -0,0 +1,18 @@
object Test {
// When the refchecks compiler phase checks if Tuple2 has the
// @deprecated annotation, it forces the info for the
// `@deprecatedInheritance` annotation (the only annotation on
// class Tuple2.
//
// Because we are compiling with `-sourcpath` that contains a
// source file for `deprecatedInheritance`, this triggers a
// `compileLate` of that file (which basically runs all previous
// compiler phases on that file.)
//
// `compileLate` assumes that all of the phases are subclasses
// of `GlobalPhase`, rather than just `Phase`. This triggers a
// `ClassCastException` when it encounters SBT's custom
// API phase.
new Tuple2("", "")
}

View File

@ -0,0 +1,4 @@
package scala
private[scala] // for now, this needs to be generalized to communicate other modifier deltas
class deprecatedInheritance(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation

View File

@ -0,0 +1 @@
> compile