Skip to content

Commit

Permalink
approximate type parameters and references by name
Browse files Browse the repository at this point in the history
not as accurate, but simpler.
(cherry picked from commit 864580a)

Conflicts:

	compile/api/APIUtil.scala
	compile/api/TagTypeVariables.scala
  • Loading branch information
harrah authored and dragos committed May 14, 2012
1 parent c2c4338 commit d7d78d6
Show file tree
Hide file tree
Showing 9 changed files with 21 additions and 234 deletions.
27 changes: 0 additions & 27 deletions compile/api/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,6 @@ object APIUtil
new Modifiers( x(0), x(1), x(2), x(3), x(4), x(5) )
}

def verifyTypeParameters(s: SourceAPI): Boolean =
{
val check = new CheckTypeParameters
val invalid = check(s)
if(!invalid.isEmpty) println("References to undefined type parameters: " + invalid.mkString(", "))
invalid.isEmpty
}
private[this] class CheckTypeParameters extends Visit
{
private val defined = new HashSet[Int]
private val referenced = new HashSet[Int]
def apply(s: SourceAPI): List[Int] =
{
super.visitAPI(s)
(referenced filterNot defined).toList
}
override def visitTypeParameter(parameter: TypeParameter)
{
defined += parameter.id
super.visitTypeParameter(parameter)
}
override def visitParameterRef(ref: ParameterRef)
{
referenced += ref.id
super.visitParameterRef(ref)
}
}
def minimize(api: SourceAPI): SourceAPI =
new SourceAPI(api.packages, minimizeDefinitions(api.definitions))
def minimizeDefinitions(ds: Array[Definition]): Array[Definition] =
Expand Down
5 changes: 2 additions & 3 deletions compile/api/ClassToAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,8 @@ object ClassToAPI
new api.TypeParameter(typeVariable(tp), emptyAnnotationArray, emptyTypeParameterArray, api.Variance.Invariant, NothingRef, upperBounds(tp.getBounds))

// needs to be stable across compilations
// preferably, it would be a proper unique id based on de Bruijn index
def typeVariable[T <: GenericDeclaration](tv: TypeVariable[T]): Int =
reduceHash((name(tv.getGenericDeclaration) + " " + tv.getName).getBytes)
def typeVariable[T <: GenericDeclaration](tv: TypeVariable[T]): String =
name(tv.getGenericDeclaration) + " " + tv.getName

def reduceHash(in: Array[Byte]): Int =
(0 /: in)( (acc, b) => (acc * 43) ^ b)
Expand Down
15 changes: 4 additions & 11 deletions compile/api/HashAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@ package xsbt.api

import xsbti.api._
import util.MurmurHash
import TagTypeVariables.TypeVars
import HashAPI.Hash

object HashAPI
{
type Hash = Int
def apply(a: SourceAPI): Hash =
{
/** de Bruijn levels for type parameters in source a and b*/
val tags = TagTypeVariables(a)
(new HashAPI(tags, false, true)).hashAPI(a)
}
(new HashAPI(false, true)).hashAPI(a)
}

final class HashAPI(tags: TypeVars, includePrivate: Boolean, includeParamNames: Boolean)
final class HashAPI(includePrivate: Boolean, includeParamNames: Boolean)
{
import scala.collection.mutable
import MurmurHash._
Expand Down Expand Up @@ -245,6 +240,7 @@ final class HashAPI(tags: TypeVars, includePrivate: Boolean, includeParamNames:
def hashTypeParameters(parameters: Seq[TypeParameter]) = hashSeq(parameters, hashTypeParameter)
def hashTypeParameter(parameter: TypeParameter)
{
hashString(parameter.id)
extend(parameter.variance.ordinal)
hashTypeParameters(parameter.typeParameters)
hashType(parameter.lowerBound)
Expand Down Expand Up @@ -283,10 +279,7 @@ final class HashAPI(tags: TypeVars, includePrivate: Boolean, includeParamNames:
def hashParameterRef(p: ParameterRef)
{
extend(ParameterRefHash)
tags.get(p.id) match {
case Some((a,b)) => extend(a); extend(b)
case None => extend(-1)
}
hashString(p.id)
}
def hashSingleton(s: Singleton)
{
Expand Down
23 changes: 6 additions & 17 deletions compile/api/SameAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object TopLevel
def definitions(i: Iterable[SourceAPI]) = SameAPI.separateDefinitions(i.toSeq.flatMap( _.definitions ))
def names(s: Iterable[Definition]): Set[String] = Set() ++ s.map(_.name)
}
import TagTypeVariables.TypeVars

/** Checks the API of two source files for equality.*/
object SameAPI
{
Expand All @@ -54,11 +54,7 @@ object SameAPI
println("\n=========== API #2 ================")
println(ShowAPI.show(b))*/

/** de Bruijn levels for type parameters in source a and b*/
val tagsA = TagTypeVariables(a)
val tagsB = TagTypeVariables(b)

val result = (new SameAPI(tagsA,tagsB, false, true)).check(a,b)
val result = (new SameAPI(false, true)).check(a,b)
val end = System.currentTimeMillis
//println(" API comparison took: " + (end - start) / 1000.0 + " s")
result
Expand Down Expand Up @@ -97,13 +93,11 @@ object SameAPI
case _ => true
}
}
/** Used to implement API equality. All comparisons must be done between constructs in source files `a` and `b`. For example, when doing:
* `sameDefinitions(as, bs)`, `as` must be definitions from source file `a` and `bs` must be definitions from source file `b`. This is in order
* to properly handle type parameters, which must be computed for each source file and then referenced during comparison.
/** Used to implement API equality.
*
* If `includePrivate` is true, `private` and `private[this]` members are included in the comparison. Otherwise, those members are excluded.
*/
class SameAPI(tagsA: TypeVars, tagsB: TypeVars, includePrivate: Boolean, includeParamNames: Boolean)
class SameAPI(includePrivate: Boolean, includeParamNames: Boolean)
{
import SameAPI._

Expand Down Expand Up @@ -301,13 +295,8 @@ class SameAPI(tagsA: TypeVars, tagsB: TypeVars, includePrivate: Boolean, include
debug(sameType(a.upperBound, b.upperBound), "Different upper bound") &&
sameTags(a.id, b.id)
}
// until dangling type parameter references are straightened out in API phase, approximate
def sameTags(a: Int, b: Int): Boolean =
{
val ta = tagsA.get(a)
val tb = tagsB.get(b)
debug(ta == tb, "Different type parameter bindings: " + ta + "(" + a + "), " + tb + "(" + b + ")")
}
def sameTags(a: String, b: String): Boolean =
debug(a == b, "Different type parameter bindings: " + a + ", " + b)

def sameType(a: Type, b: Type): Boolean =
samePending(a,b)(sameTypeDirect)
Expand Down
166 changes: 0 additions & 166 deletions compile/api/TagTypeVariables.scala

This file was deleted.

9 changes: 4 additions & 5 deletions compile/interface/API.scala
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
else if(sym.isRoot || sym.isRootPackage) Constants.emptyType
else new xsbti.api.Projection(simpleType(in, pre), sym.nameString)
}

private def reference(sym: Symbol): xsbti.api.ParameterRef = new xsbti.api.ParameterRef(sym.id)

private def reference(sym: Symbol): xsbti.api.ParameterRef = new xsbti.api.ParameterRef(tparamID(sym))

private def annotations(in: Symbol, as: List[AnnotationInfo]): Array[xsbti.api.Annotation] = as.toArray[AnnotationInfo].map(annotation(in,_))
private def annotation(in: Symbol, a: AnnotationInfo) =
Expand Down Expand Up @@ -342,11 +340,12 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
val variance = if(varianceInt < 0) Contravariant else if(varianceInt > 0) Covariant else Invariant
viewer(in).memberInfo(s) match
{
case TypeBounds(low, high) => new xsbti.api.TypeParameter( s.id, annots, typeParameters(in, s), variance, processType(in, low), processType(in, high) )
case PolyType(typeParams, base) => new xsbti.api.TypeParameter( s.id, annots, typeParameters(in, typeParams), variance, processType(in, base.bounds.lo), processType(in, base.bounds.hi))
case TypeBounds(low, high) => new xsbti.api.TypeParameter( tparamID(s), annots, typeParameters(in, s), variance, processType(in, low), processType(in, high) )
case PolyType(typeParams, base) => new xsbti.api.TypeParameter( tparamID(s), annots, typeParameters(in, typeParams), variance, processType(in, base.bounds.lo), processType(in, base.bounds.hi))
case x => error("Unknown type parameter info: " + x.getClass)
}
}
private def tparamID(s: Symbol) = s.fullName
private def selfType(in: Symbol, s: Symbol): xsbti.api.Type = processType(in, s.thisSym.typeOfThis)

private def classLike(in: Symbol, c: Symbol): ClassLike = classLikeCache.getOrElseUpdate( (in,c), mkClassLike(in, c))
Expand Down
6 changes: 3 additions & 3 deletions compile/persist/APIFormats.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ trait APIFormats extends FormatExtra
implicit def formatExistential(implicit t: Format[Type], tps: Format[Array[TypeParameter]]): Format[Existential] =
p2( (e: Existential) => (e.baseType, e.clause) )( new Existential(_,_) )(t,tps)

implicit def formatParameterRef(implicit i: Format[Int]): Format[ParameterRef] =
wrap[ParameterRef, Int](_.id, new ParameterRef(_))(i)
implicit def formatParameterRef(implicit i: Format[String]): Format[ParameterRef] =
wrap[ParameterRef, String](_.id, new ParameterRef(_))(i)

// cyclic with many formats
def formatType(implicit s: Format[SimpleType], a: Format[Annotated], st: Format[Structure], e: Format[Existential], po: Format[Polymorphic]): Format[Type] =
Expand Down Expand Up @@ -175,7 +175,7 @@ trait APIFormats extends FormatExtra
implicit def formatModifiers(implicit bf: Format[Byte]): Format[Modifiers] =
wrap[Modifiers, Byte]( modifiersToByte, byteToModifiers )

def formatTypeParameter(tps: Format[TypeParameter] => Format[Array[TypeParameter]])(implicit as: Format[Array[Annotation]], t: Format[Type], v: Format[Variance], i: Format[Int]): Format[TypeParameter] =
def formatTypeParameter(tps: Format[TypeParameter] => Format[Array[TypeParameter]])(implicit as: Format[Array[Annotation]], t: Format[Type], v: Format[Variance], i: Format[String]): Format[TypeParameter] =
{
lazy val ltps: Format[Array[TypeParameter]] = lazyFormat( tps(ltp) )
lazy val ltp = p6( (tp: TypeParameter) => (tp.id, tp.annotations, tp.typeParameters, tp.variance, tp.lowerBound, tp.upperBound))(new TypeParameter(_,_,_,_,_,_))(i, as, ltps, v, t, t)
Expand Down
2 changes: 1 addition & 1 deletion interface/other
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ MethodParameter
modifier: ParameterModifier

TypeParameter
id: Int
id: String
annotations: Annotation*
typeParameters : TypeParameter*
variance: Variance
Expand Down
2 changes: 1 addition & 1 deletion interface/type
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Type
prefix : SimpleType
id: String
ParameterRef
id: Int
id: String
Singleton
path: Path
ConstantType
Expand Down

0 comments on commit d7d78d6

Please sign in to comment.