summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2010-08-10 21:12:13 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2010-08-10 21:12:13 +0000
commit41bfef808702c291d69d5f742628e1304632bdda (patch)
tree264d080aca6a0e0059d845cb44716d0cab2afba3 /src/compiler/scala/tools/nsc/typechecker/Implicits.scala
parent04c38829b6fdb03ab62ee20ebff6a56c519bb358 (diff)
downloadscala-41bfef808702c291d69d5f742628e1304632bdda.tar.gz
scala-41bfef808702c291d69d5f742628e1304632bdda.tar.bz2
scala-41bfef808702c291d69d5f742628e1304632bdda.zip
different approach to manifests of type par...
different approach to manifests of type parameters: before, ambiguity was prevented by leaving type inference failures (Nothing was inferred) in the expression that needs an implicit manifest -- we now put these back in undetparams (maybe they will be inferred) and when we need to produce a manifest for an undetermined parameter (it ended up not being inferred), we assume it will get instantiated to Nothing (but for now don't actually reflect that in the SearchResult, as instantiate should take care of that anyway) see test file for use case that works with this new scheme, but did not work before: the eager instantiation of type params to Nothing before implicit search even got started would indeed prevent ambiguity -- unfortunately it also ruled out valid code like this (where the type parameter is inferred successfully by the time the manifest is needed) review by odersky
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 7452ac678b..a6549021c5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -27,6 +27,7 @@ self: Analyzer =>
import definitions._
def traceImplicits = printTypings
+ import global.typer.{printTyping, deindentTyping, indentTyping}
/** Search for an implicit value. See the comment on `result` at the end of class `ImplicitSearch`
* for more info how the search is conducted.
@@ -42,6 +43,8 @@ self: Analyzer =>
* @return A search result
*/
def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = {
+ printTyping("Beginning implicit search for "+ tree +" expecting "+ pt + (if(isView) " looking for a view" else ""))
+ indentTyping()
val rawTypeStart = startCounter(rawTypeImpl)
val findMemberStart = startCounter(findMemberImpl)
val subtypeStart = startCounter(subtypeImpl)
@@ -54,6 +57,8 @@ self: Analyzer =>
stopCounter(rawTypeImpl, rawTypeStart)
stopCounter(findMemberImpl, findMemberStart)
stopCounter(subtypeImpl, subtypeStart)
+ deindentTyping()
+ printTyping("Implicit search yielded: "+ result)
result
}
@@ -209,11 +214,10 @@ self: Analyzer =>
*/
class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context)
extends Typer(context0) {
-
+ printTyping("begin implicit search: "+(tree, pt, isView, context.outer.undetparams))
// assert(tree.isEmpty || tree.pos.isDefined, tree)
import infer._
-
/** Is implicit info `info1` better than implicit info `info2`?
*/
def improves(info1: ImplicitInfo, info2: ImplicitInfo) = {
@@ -424,7 +428,7 @@ self: Analyzer =>
incCounter(plausiblyCompatibleImplicits)
- //if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List())+"/"+info.pre+"/"+isStable(info.pre))
+ printTyping("typed impl for "+wildPt+"? "+info.name +":"+ depoly(info.tpe)+ " orig info= "+ info.tpe +"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List())+"/"+info.pre+"/"+isStable(info.pre))
if (matchesPt(depoly(info.tpe), wildPt, List()) && isStable(info.pre)) {
incCounter(matchingImplicits)
@@ -433,7 +437,7 @@ self: Analyzer =>
if (info.pre == NoPrefix) Ident(info.name)
else Select(gen.mkAttributedQualifier(info.pre), info.name)
}
- if (traceImplicits) println("typed impl?? "+info.name+":"+info.tpe+" ==> "+itree+" with pt = "+pt+", wildpt = "+wildPt)
+ printTyping("typedImplicit0 typing"+ itree +" with wildpt = "+ wildPt +" from implicit "+ info.name+":"+info.tpe)
def fail(reason: String): SearchResult = {
if (settings.XlogImplicits.value)
inform(itree+" is not a valid implicit value for "+pt+" because:\n"+reason)
@@ -452,10 +456,10 @@ self: Analyzer =>
incCounter(typedImplicits)
- if (traceImplicits) println("typed implicit "+itree1+":"+itree1.tpe+", pt = "+wildPt)
+ printTyping("typed implicit "+itree1+":"+itree1.tpe+", pt = "+wildPt)
val itree2 = if (isView) (itree1: @unchecked) match { case Apply(fun, _) => fun }
else adapt(itree1, EXPRmode, wildPt)
- if (traceImplicits) println("adapted implicit "+itree1.symbol+":"+itree2.tpe+" to "+wildPt)
+ printTyping("adapted implicit "+itree1.symbol+":"+itree2.tpe+" to "+wildPt)
def hasMatchingSymbol(tree: Tree): Boolean = (tree.symbol == info.sym) || {
tree match {
case Apply(fun, _) => hasMatchingSymbol(fun)
@@ -469,7 +473,7 @@ self: Analyzer =>
else if (hasMatchingSymbol(itree1)) {
val tvars = undetParams map freshVar
if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars), undetParams)) {
- if (traceImplicits) println("tvars = "+tvars+"/"+(tvars map (_.constr)))
+ printTyping("tvars = "+tvars+"/"+(tvars map (_.constr)))
val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt),
false, lubDepth(List(itree2.tpe, pt)))
@@ -498,7 +502,8 @@ self: Analyzer =>
// println("RESULT = "+itree+"///"+itree1+"///"+itree2)//DEBUG
result
} else {
- if (traceImplicits) println("incompatible: "+itree2.tpe+" does not match "+pt.instantiateTypeParams(undetParams, tvars))
+ printTyping("incompatible: "+itree2.tpe+" does not match "+pt.instantiateTypeParams(undetParams, tvars))
+
SearchFailure
}
} else if (settings.XlogImplicits.value)
@@ -840,6 +845,8 @@ self: Analyzer =>
} else if (sym.isExistentiallyBound && full) {
manifestFactoryCall("wildcardType", tp,
findManifest(tp.bounds.lo), findManifest(tp.bounds.hi))
+ } else if(undetParams contains sym) { // looking for a manifest of a type parameter that hasn't been inferred by now, can't do much, but let's not fail
+ mot(NothingClass.tpe) // TODO: should we include the mapping from sym -> NothingClass.tpe in the SearchResult? (it'll get instantiated to nothing anyway, I think)
} else {
EmptyTree // a manifest should have been found by normal searchImplicit
}