Skip to content

Commit

Permalink
SI-8046 Only use fast TypeRef#baseTypeSeq with concrete base types
Browse files Browse the repository at this point in the history
We can only compute the base type sequence (BTS) of a `TypeRef` by
element-wise transforming the BTS of the referenced symbol if
there are no abstract types in its BTS type symbols.

In the now-working test case, `pos/t8046.scala`, the difference
between the old and new calculation of the BTS is:

    this                 = Three.this.Alias[Int]
    sym.info.baseTypeSeq = BTS(One.this.Op[A],Any)
    mapped BTS           = BTS(Three.this.Op[Int],Any)
    full BTS             = BTS(Three.this.Op[Int],Int => Int,Object,Any)

The change to account for PolyType in ArgsTypeRef#transform is now
needed to avoid the full BTS of:

    BTS(Three.this.Op[A],A => A,Object,Any)

Interestingly, everything actually works without that change.
  • Loading branch information
retronym committed Dec 10, 2013
1 parent 0de991f commit 6f42bd6
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 3 deletions.
13 changes: 11 additions & 2 deletions src/reflect/scala/reflect/internal/Types.scala
Expand Up @@ -1999,7 +1999,9 @@ trait Types
if (sym.typeParams.size != args.size)
devWarning(s"$this.transform($tp), but tparams.isEmpty and args=$args")

asSeenFromOwner(tp).instantiateTypeParams(sym.typeParams, args)
val GenPolyType(tparams, result) = asSeenFromOwner(tp)
assert((tparams eq Nil) || tparams == sym.typeParams, (tparams, sym.typeParams))
result.instantiateTypeParams(sym.typeParams, args)
}

// note: does not go through typeRef. There's no need to because
Expand Down Expand Up @@ -2309,7 +2311,14 @@ trait Types
}
thisInfo.decls
}
protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform
protected[Types] def baseTypeSeqImpl: BaseTypeSeq =
if (sym.info.baseTypeSeq exists (_.typeSymbolDirect.isAbstractType))
// SI-8046 base type sequence might have more elements in a subclass, we can't map it element wise.
transform(sym.info).baseTypeSeq
else
// Optimization: no abstract types, we can compute the BTS of this TypeRef as an element-wise map
// of the BTS of the referenced symbol.
sym.info.baseTypeSeq map transform

override def baseTypeSeq: BaseTypeSeq = {
val cache = baseTypeSeqCache
Expand Down
Expand Up @@ -5,7 +5,7 @@ trait One {

trait Three extends One {
trait Op[A] extends (A => A)

def f1(f: Op[Int]) = f(5)
def f2(f: Alias[Int]) = f(5)
def f3[T <: Op[Int]](f: T) = f(5)
Expand Down
2 changes: 2 additions & 0 deletions test/files/run/t8046.check
@@ -0,0 +1,2 @@
List(trait Op, trait Function1, class Object, class Any)
BTS(T,Three.this.Op[Int],Int => Int,Object,Any)
18 changes: 18 additions & 0 deletions test/files/run/t8046/Test.scala
@@ -0,0 +1,18 @@
import scala.tools.partest._

object Test extends DirectTest {
override def code = ""
override def extraSettings: String = "-usejavacp"

override def show() {
val c = newCompiler()
new c.Run
import c._

val f4 = typeOf[Three].member(newTermName("f4"))
val f4ParamInfo = f4.paramss.head.head.info
println(f4ParamInfo.baseClasses)
println(f4ParamInfo.baseTypeSeq)
}
}

13 changes: 13 additions & 0 deletions test/files/run/t8046/t8046c.scala
@@ -0,0 +1,13 @@
import language._

trait One {
type Op[A]
type Alias[A] = Op[A]
}

trait Three extends One {
trait Op[A] extends (A => A)

def f4[T <: Alias[Int]](f: T) = 0
}

0 comments on commit 6f42bd6

Please sign in to comment.