Skip to content

Commit

Permalink
Merge pull request typesafehub#65 from eed3si9n/wip/58
Browse files Browse the repository at this point in the history
Rebased FPORT: Improvements to ExtractAPI (#2413 & #2414)
  • Loading branch information
dwijnand committed Feb 23, 2016
2 parents b5127fc + e5a3774 commit 59621dd
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class B {
def bar(dummy: String)(dummy2: String): A = new A(0)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object C extends App {
println(new B().bar("")("").x)
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ abstract class Compat {
}
lazy val AnyValClass = global.rootMirror.getClassIfDefined("scala.AnyVal")

def isAnyValSubtype(sym: Symbol): Boolean = sym.isNonBottomSubClass(AnyValClass)

def isDerivedValueClass(sym: Symbol): Boolean =
sym.isNonBottomSubClass(AnyValClass) && !definitions.ScalaValueClasses.contains(sym)
}

object MacroExpansionOf {
Expand Down
20 changes: 7 additions & 13 deletions internal/compiler-bridge/src-2.10/main/scala/xsbt/ExtractAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,23 +207,17 @@ class ExtractAPI[GlobalType <: CallbackGlobal](

val hasValueClassAsParameter: Boolean = {
import MirrorHelper._
s.asMethod.paramss.flatten map (_.info) exists (t => isAnyValSubtype(t.typeSymbol))
s.asMethod.paramss.flatten map (_.info) exists (t => isDerivedValueClass(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 => isDerivedValueClass(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] =
{
Expand Down
22 changes: 8 additions & 14 deletions internal/compiler-bridge/src/main/scala/xsbt/ExtractAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -200,22 +200,16 @@ class ExtractAPI[GlobalType <: CallbackGlobal](
{

val hasValueClassAsParameter: Boolean =
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 NullaryMethodType(resultType) => isAnyValSubtype(resultType.typeSymbol)
case resultType => isAnyValSubtype(resultType.typeSymbol)
}
s.asMethod.paramss.flatten map (_.info) exists (_.typeSymbol.isDerivedValueClass)

def hasValueClassAsReturnType(tpe: Type): Boolean = tpe match {
case PolyType(_, base) => hasValueClassAsReturnType(base)
case MethodType(_, resultType) => hasValueClassAsReturnType(resultType)
case NullaryMethodType(resultType) => hasValueClassAsReturnType(resultType)
case resultType => resultType.typeSymbol.isDerivedValueClass
}

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] =
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,16 @@ class NameHashingSpecification extends UnitSpec {
}

/**
* Checks that private members do NOT contribute to name hashes.
* Test for https://github.com/sbt/sbt/issues/2324
*/
* Checks that private members do NOT contribute to name hashes.
* Test for https://github.com/sbt/sbt/issues/2324
*/
it should "private members in classes do not contribute to name hashes" in {
/* class Foo { private val x } */
val classFoo =
simpleClass("Foo",
simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty)))
simpleClass(
"Foo",
simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty))
)
val nameHashes = nameHashesForClass(classFoo)
// make sure there's no name hash for the private member "x"
assert(Seq("Foo") === nameHashes.regularMembers.map(_.name).toSeq)
Expand Down

0 comments on commit 59621dd

Please sign in to comment.