Merge pull request #2413 from smarter/fix/vc-return-type

[0.13.10] Always invalidate API when return type is a value class
This commit is contained in:
Dale Wijnand 2016-01-25 07:02:20 +00:00
commit 03524e3329
4 changed files with 32 additions and 12 deletions

View File

@ -208,20 +208,14 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
s.asMethod.paramss.flatten map (_.info) exists (t => isAnyValSubtype(t.typeSymbol))
}
// Note: We only inspect the "outermost type" (i.e. no recursion) because we don't need to
// inspect after erasure a function that would, for instance, return a function that returns
// a subtype of AnyVal.
val hasValueClassAsReturnType: Boolean = {
val tpe = viewer(in).memberInfo(s)
tpe match {
case PolyType(_, base) => isAnyValSubtype(base.typeSymbol)
case MethodType(_, resultType) => isAnyValSubtype(resultType.typeSymbol)
case Nullary(resultType) => isAnyValSubtype(resultType.typeSymbol)
case resultType => isAnyValSubtype(resultType.typeSymbol)
}
def hasValueClassAsReturnType(tpe: Type): Boolean = tpe match {
case PolyType(_, base) => hasValueClassAsReturnType(base)
case MethodType(_, resultType) => hasValueClassAsReturnType(resultType)
case Nullary(resultType) => hasValueClassAsReturnType(resultType)
case resultType => isAnyValSubtype(resultType.typeSymbol)
}
val inspectPostErasure = hasValueClassAsParameter || hasValueClassAsReturnType
val inspectPostErasure = hasValueClassAsParameter || hasValueClassAsReturnType(viewer(in).memberInfo(s))
def build(t: Type, typeParams: Array[xsbti.api.TypeParameter], valueParameters: List[xsbti.api.ParameterList]): List[xsbti.api.Def] =
{

View File

@ -0,0 +1,3 @@
class B {
def bar(dummy: String)(dummy2: String): A = new A(0)
}

View File

@ -0,0 +1,3 @@
object C extends App {
println(new B().bar("")("").x)
}

View File

@ -1,3 +1,4 @@
## Case 1: value class as parameter of method
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B0.scala src/main/scala/B.scala
$ copy-file changes/C0.scala src/main/scala/C.scala
@ -13,6 +14,8 @@ $ copy-file changes/A1.scala src/main/scala/A.scala
# This means that we have invalidated C.scala, as expected!
-> compile
## Case 2: value class as return type of method with no parameter lists
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B1.scala src/main/scala/B.scala
$ copy-file changes/C1.scala src/main/scala/C.scala
@ -28,3 +31,20 @@ $ copy-file changes/A1.scala src/main/scala/A.scala
# because A is now a value class.
> run
## Case 3: value class as return type of method with multiple parameter lists
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B2.scala src/main/scala/B.scala
$ copy-file changes/C2.scala src/main/scala/C.scala
# A is a normal class. B.bar takes two dummy arguments and returns an instance of A. C calls B.bar("")("").
> compile
> run
# Make A a value class.
$ copy-file changes/A1.scala src/main/scala/A.scala
# The code compiles. It will run iff C is recompiled because the signature of B.bar has changed,
# because A is now a value class.
> run