1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
* filter: inliner warning; re-run with
*/
import scala.tools.nsc._
import scala.tools.partest.DirectTest
import scala.collection.{ mutable, immutable, generic }
import scala.language.{postfixOps, implicitConversions}
import scala.reflect.runtime.{universe => ru}
// necessary to avoid bincompat with scala-partest compiled against the old compiler
abstract class CompilerTest extends DirectTest {
def check(source: String, unit: global.CompilationUnit): Unit
lazy val global: Global = newCompiler()
lazy val units: List[global.CompilationUnit] = compilationUnits(global)(sources: _ *)
import global._
import definitions.{ compilerTypeFromTag }
override def extraSettings = "-feature -usejavacp -d " + testOutput.path
def show() = (sources, units).zipped foreach check
// Override at least one of these...
def code = ""
def sources: List[String] = List(code)
// Utility functions
class MkType(sym: Symbol) {
def apply[M](implicit t: ru.TypeTag[M]): Type =
if (sym eq NoSymbol) NoType
else appliedType(sym, compilerTypeFromTag(t))
}
implicit def mkMkType(sym: Symbol) = new MkType(sym)
def allMembers(root: Symbol): List[Symbol] = {
def loop(seen: Set[Symbol], roots: List[Symbol]): List[Symbol] = {
val latest = roots flatMap (_.info.members) filterNot (seen contains _)
if (latest.isEmpty) seen.toList.sortWith(_ isLess _)
else loop(seen ++ latest, latest)
}
loop(Set(), List(root))
}
class SymsInPackage(pkgName: String) {
def pkg = rootMirror.getPackage(TermName(pkgName))
def classes = allMembers(pkg) filter (_.isClass)
def modules = allMembers(pkg) filter (_.isModule)
def symbols = classes ++ terms filterNot (_ eq NoSymbol)
def terms = allMembers(pkg) filter (s => s.isTerm && !s.isConstructor)
def tparams = classes flatMap (_.info.typeParams)
def tpes = symbols map (_.tpe) distinct
}
}
/** It's too messy but it's better than not having it.
*/
object Test extends CompilerTest {
import global._
import definitions._
override def sources = List(lambdaLift)
def lambdaLift = """
package ll {
class A1
class A2
class X
class C[T1]() {
class I[T2]() {
def t1(): T1 = ???
def t2(): T2 = ???
def thisC(): C.this.type = ???
def thisI(): I.this.type = ???
}
}
class D[T3]() extends C[T3]() {
val cD: C[List[T3]] = ???
class J[T4]() extends cD.I[T4]()
}
object Z {
val dZ: D[A1] = ???
val jZ: dZ.J[A2] = ???
def kz[P <: dZ.J[A2]]: dZ.J[P] = ???
}
}
"""
object syms extends SymsInPackage("ll") {
def isPossibleEnclosure(encl: Symbol, sym: Symbol) = sym.enclClassChain drop 1 exists (_ isSubClass encl)
def isInterestingPrefix(pre: Type) = pre.typeConstructor.typeParams.nonEmpty && pre.members.exists(_.isType)
def asSeenPrefixes = tpes map (_.finalResultType) distinct
def typeRefPrefixes = asSeenPrefixes filter isInterestingPrefix
def nestsIn(outer: Symbol) = classes filter (c => c.enclClassChain drop 1 exists(_ isSubClass outer))
def typeRefs(targs: List[Type]) = (
for (p <- typeRefPrefixes ; c <- classes filter (isPossibleEnclosure(p.typeSymbol, _)) ; a <- targs) yield
typeRef(p, c, List(a))
)
val wfmt = "%-" + 25 + "s"
def to_s(x: Any): String = wfmt.format(x.toString.replaceAll("""\bll\.""", ""))
def fmt(args: Any*): String = {
(args map to_s mkString " ").replaceAll("""\s+$""", "")
}
def fname(sym: Symbol) = {
val p = "" + sym.owner.name
val x = if (sym.owner.isPackageClass || sym.owner.isModuleClass || sym.owner.isTerm) "." else "#"
sym.kindString + " " + p + x + sym.name
}
def permuteAsSeenFrom(targs: List[Type]) = (
for {
tp <- typeRefs(targs filterNot (_ eq NoType))
prefix <- asSeenPrefixes
if tp.prefix != prefix
site <- classes
seen = tp.asSeenFrom(prefix, site)
if tp != seen
if !seen.isInstanceOf[ExistentialType]
}
yield ((site, tp, prefix, seen))
)
def block(label: Any)(lines: List[String]): List[String] = {
val first = "" + label + " {"
val last = "}"
first +: lines.map(" " + _) :+ last
}
def permute(targs: List[Type]): List[String] = {
permuteAsSeenFrom(targs).groupBy(_._1).toList.sortBy(_._1.toString) flatMap {
case (site, xs) =>
block(fmt(site)) {
fmt("type", "seen from prefix", "is") ::
fmt("----", "----------------", "--") :: {
xs.groupBy(_._2).toList.sortBy(_._1.toString) flatMap {
case (tp, ys) =>
(ys map { case (_, _, prefix, seen) => fmt(tp, prefix, seen) }).sorted.distinct
}
}
}
}
}
}
def pretty(xs: List[_]) = if (xs.isEmpty) "" else xs.mkString("\n ", "\n ", "\n")
def signaturesIn(info: Type): List[String] = (
info.members.toList
filterNot (s => s.isType || s.owner == ObjectClass || s.owner == AnyClass || s.isConstructor)
map (_.defString)
)
def check(source: String, unit: global.CompilationUnit) = {
import syms._
exitingTyper {
val typeArgs = List[Type](IntClass.tpe, ListClass[Int]) ++ tparams.map(_.tpe)
permute(typeArgs) foreach println
}
for (x <- classes ++ terms) {
afterEachPhase(signaturesIn(x.tpe)) collect {
case (ph, sigs) if sigs.nonEmpty =>
println(sigs.mkString(x + " { // after " + ph + "\n ", "\n ", "\n}\n"))
}
}
}
}
|