summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-12 09:09:48 -0800
committerPaul Phillips <paulp@improving.org>2012-01-12 09:32:27 -0800
commit15372027c762b18bccf231b9810e9db3415e7f5a (patch)
treeb1b81772dc1a93c1638163e521182387edd03150
parent5f5029d2ac6348ecb07fc11f6656621c662ced92 (diff)
downloadscala-15372027c762b18bccf231b9810e9db3415e7f5a.tar.gz
scala-15372027c762b18bccf231b9810e9db3415e7f5a.tar.bz2
scala-15372027c762b18bccf231b9810e9db3415e7f5a.zip
Streamlining output of -Yinfer-debug.
Also exposed some typevar related code outside a method.
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala40
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala48
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala50
3 files changed, 55 insertions, 83 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 43905ee344..6d4332216c 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -943,30 +943,12 @@ trait Types extends api.Types { self: SymbolTable =>
*/
//TODO: use narrow only for modules? (correct? efficiency gain?)
def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
- var suspension: mutable.HashSet[TypeVar] = null
// if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
// replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
// without this, the matchesType call would lead to type variables on both sides
// of a subtyping/equality judgement, which can lead to recursive types being constructed.
// See (t0851) for a situation where this happens.
- if (!this.isGround) {
- // PP: The foreach below was formerly expressed as:
- // for(tv @ TypeVar(_, _) <- this) { suspension suspend tv }
- //
- // The tree checker failed this saying a TypeVar is required, but a (Type @unchecked) was found.
- // This is a consequence of using a pattern match and variable binding + ticket #1503, which
- // was addressed by weakening the type of bindings in pattern matches if they occur on the right.
- // So I'm not quite sure why this works at all, as the checker is right that it is mistyped.
- // For now I modified it as below, which achieves the same without error.
- //
- // make each type var in this type use its original type for comparisons instead of collecting constraints
- val susp = new mutable.HashSet[TypeVar] // use a local val so it remains unboxed
- this foreach {
- case tv: TypeVar => tv.suspended = true; susp += tv
- case _ =>
- }
- suspension = susp
- }
+ val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
incCounter(findMemberCount)
val start = startTimer(findMemberNanos)
@@ -6101,6 +6083,26 @@ trait Types extends api.Types { self: SymbolTable =>
if (ts exists (_.isNotNull)) res.notNull else res
}
+
+ /** A list of the typevars in a type. */
+ def typeVarsInType(tp: Type): List[TypeVar] = {
+ var tvs: List[TypeVar] = Nil
+ tp foreach {
+ case t: TypeVar => tvs ::= t
+ case _ =>
+ }
+ tvs.reverse
+ }
+ /** Make each type var in this type use its original type for comparisons instead
+ * of collecting constraints.
+ */
+ def suspendTypeVarsInType(tp: Type): List[TypeVar] = {
+ val tvs = typeVarsInType(tp)
+ // !!! Is it somehow guaranteed that this will not break under nesting?
+ // In general one has to save and restore the contents of the field...
+ tvs foreach (_.suspended = true)
+ tvs
+ }
/** Compute lub (if `variance == 1`) or glb (if `variance == -1`) of given list
* of types `tps`. All types in `tps` are typerefs or singletypes
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 3b90eaeed7..918eb749c8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -45,8 +45,9 @@ trait Implicits {
* @return A search result
*/
def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = {
- printInference("[inferImplicit%s] pt = %s".format(
- if (isView) " view" else "", pt)
+ printInference("[infer %s] %s with pt=%s in %s".format(
+ if (isView) "view" else "implicit",
+ tree, pt, context.owner.enclClass)
)
printTyping(
ptBlock("infer implicit" + (if (isView) " view" else ""),
@@ -65,7 +66,7 @@ trait Implicits {
printTyping("typing implicit: %s %s".format(tree, context.undetparamsString))
val result = new ImplicitSearch(tree, pt, isView, context.makeImplicit(reportAmbiguous)).bestImplicit
- printInference("[inferImplicit] result: " + result)
+ printInference("[infer implicit] inferred " + result)
context.undetparams = context.undetparams filterNot result.subst.from.contains
stopTimer(implicitNanos, start)
@@ -395,7 +396,6 @@ trait Implicits {
* @pre `info.tpe` does not contain an error
*/
private def typedImplicit(info: ImplicitInfo, ptChecked: Boolean): SearchResult = {
- printInference("[typedImplicit] " + info)
(context.openImplicits find { case (tp, sym) => sym == tree.symbol && dominates(pt, tp)}) match {
case Some(pending) =>
// println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG
@@ -614,16 +614,15 @@ trait Implicits {
info.sym.fullLocationString, itree1.symbol.fullLocationString))
else {
val tvars = undetParams map freshVar
-
- if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars), undetParams)) {
- printInference(
- ptBlock("matchesPt",
- "itree1" -> itree1,
- "tvars" -> tvars,
- "undetParams" -> undetParams
- )
- )
-
+ def ptInstantiated = pt.instantiateTypeParams(undetParams, tvars)
+
+ printInference("[search] considering %s (pt contains %s) trying %s against pt=%s".format(
+ if (undetParams.isEmpty) "no tparams" else undetParams.map(_.name).mkString(", "),
+ typeVarsInType(ptInstantiated) filterNot (_.isGround) match { case Nil => "no tvars" ; case tvs => tvs.mkString(", ") },
+ itree2.tpe, pt
+ ))
+
+ if (matchesPt(itree2.tpe, ptInstantiated, undetParams)) {
if (tvars.nonEmpty)
printTyping(ptLine("" + info.sym, "tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr)))
@@ -637,6 +636,7 @@ trait Implicits {
// we must be conservative in leaving type params in undetparams
// prototype == WildcardType: want to remove all inferred Nothings
val AdjustedTypeArgs(okParams, okArgs) = adjustTypeArgs(undetParams, tvars, targs)
+
val subst: TreeTypeSubstituter =
if (okParams.isEmpty) EmptyTreeTypeSubstituter
else {
@@ -663,11 +663,10 @@ trait Implicits {
}
val result = new SearchResult(itree2, subst)
incCounter(foundImplicits)
- printInference("[typedImplicit1] SearchResult: " + result)
+ printInference("[success] found %s for pt %s".format(result, ptInstantiated))
result
}
- else fail("incompatible: %s does not match expected type %s".format(
- itree2.tpe, pt.instantiateTypeParams(undetParams, tvars)))
+ else fail("incompatible: %s does not match expected type %s".format(itree2.tpe, ptInstantiated))
}
}
catch {
@@ -786,16 +785,11 @@ trait Implicits {
// most frequent one first
matches sortBy (x => if (isView) -x.useCountView else -x.useCountArg)
}
- def eligibleString = {
- val args = List(
- "search" -> pt,
- "target" -> tree,
- "isView" -> isView
- ) ++ eligible.map("eligible" -> _)
-
- ptBlock("Implicit search in " + context, args: _*)
- }
- printInference(eligibleString)
+ if (eligible.nonEmpty)
+ printInference("[search%s] %s with pt=%s in %s, eligible:\n %s".format(
+ if (isView) " view" else "",
+ tree, pt, context.owner.enclClass, eligible.mkString("\n "))
+ )
/** Faster implicit search. Overall idea:
* - prune aggressively
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 23dd28aac4..b1612f24ef 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -138,6 +138,9 @@ trait Infer {
def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol],
variances: List[Int], upper: Boolean, depth: Int): List[Type] = {
+ if (tvars.nonEmpty)
+ printInference("[solve types] solving for " + tparams.map(_.name).mkString(", ") + " in " + tvars.mkString(", "))
+
if (!solve(tvars, tparams, variances, upper, depth)) {
// no panic, it's good enough to just guess a solution, we'll find out
// later whether it works. *ZAP* @M danger, Will Robinson! this means
@@ -550,18 +553,6 @@ trait Infer {
throw new NoInstance("parameter lists differ in length")
val restpeInst = restpe.instantiateTypeParams(tparams, tvars)
- printInference(
- ptBlock("methTypeArgs",
- "tparams" -> tparams,
- "formals" -> formals,
- "restpe" -> restpe,
- "restpeInst" -> restpeInst,
- "argtpes" -> argtpes,
- "pt" -> pt,
- "tvars" -> tvars,
- "constraints" -> tvars.map(_.constr)
- )
- )
// first check if typevars can be fully defined from the expected type.
// The return value isn't used so I'm making it obvious that this side
@@ -599,17 +590,7 @@ trait Infer {
tvars, tparams, tparams map varianceInTypes(formals),
false, lubDepth(formals) max lubDepth(argtpes)
)
- val result = adjustTypeArgs(tparams, tvars, targs, restpe)
-
- printInference(
- ptBlock("methTypeArgs result",
- "tvars" -> tvars,
- "constraints" -> tvars.map(_.constr),
- "targs" -> targs,
- "adjusted type args" -> result
- )
- )
- result
+ adjustTypeArgs(tparams, tvars, targs, restpe)
}
private[typechecker] def followApply(tp: Type): Type = tp match {
@@ -1094,15 +1075,6 @@ trait Infer {
def inferMethodInstance(fn: Tree, undetparams: List[Symbol],
args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
case MethodType(params0, _) =>
- printInference(
- ptBlock("inferMethodInstance",
- "fn" -> fn,
- "undetparams" -> undetparams,
- "args" -> args,
- "pt0" -> pt0
- )
- )
-
try {
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
val formals = formalTypes(params0 map (_.tpe), args.length)
@@ -1112,11 +1084,19 @@ trait Infer {
val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
methTypeArgs(undetparams, formals, restpe, argtpes, pt)
+ printInference("[infer method] solving for %s in %s based on (%s)%s (%s)".format(
+ undetparams.map(_.name).mkString(", "),
+ fn.tpe,
+ argtpes.mkString(", "),
+ restpe,
+ (okparams map (_.name), okargs).zipped.map(_ + "=" + _).mkString("solved: ", ", ", "")
+ ))
+
checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")
val treeSubst = new TreeTypeSubstituter(okparams, okargs)
treeSubst traverseTrees fn :: args
- val result = leftUndet match {
+ leftUndet match {
case Nil => Nil
case xs =>
// #3890
@@ -1126,10 +1106,6 @@ trait Infer {
xs1
}
- if (result.nonEmpty)
- printInference("inferMethodInstance, still undetermined: " + result)
-
- result
}
catch ifNoInstance { msg =>
errorTree(fn, "no type parameters for " +