diff options
author | Martin Odersky <odersky@gmail.com> | 2009-10-08 18:31:44 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-10-08 18:31:44 +0000 |
commit | 9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7 (patch) | |
tree | a35cfe628c41ba4da25d7a1d9077b4298ecf3e67 /src/compiler/scala/tools/nsc/typechecker/Implicits.scala | |
parent | adb677e4bc0c2fc7e822615c08384875e06a64ee (diff) | |
download | scala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.tar.gz scala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.tar.bz2 scala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.zip |
Definite fix for #2060; fix for #2392.
Added aliases for Vector and Traversable to scala package object.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index e9ca2dd7c5..133c0c1b3e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -174,6 +174,15 @@ self: Analyzer => } } + /** An extractor for unary function types arg => res + */ + object Function1 { + def unapply(tp: Type) = tp match { + case TypeRef(_, sym, List(arg, res)) if (sym == FunctionClass(1)) => Some(arg, res) + case _ => None + } + } + /** A class that sets up an implicit search. For more info, see comments for `inferImplicit`. * @param tree The tree for which the implicit needs to be inserted. * @param pt The original expected type of the implicit. @@ -344,32 +353,33 @@ self: Analyzer => */ val wildPt = approximate(pt) - /** Does type `tp' match wildPt? - * This is the case if either `wildPt' is a HasMethodMatching type - * and `tp' has a method matching wildPt, or otherwise if - * `tp' stripped of universal quantifiers is compatible with `wildPt'. - */ - def matchesWildPt(tp: Type) = wildPt match { - case HasMethodMatching(name, argtpes, restpe) => - (tp.member(name) filter (m => isApplicableSafe(List(), m.tpe, argtpes, restpe))) != NoSymbol - case _ => - isCompatible(depoly(tp), wildPt) - } - - /** Does type `tp' match prototype `pt'? - * This is the case if either `pt' is a HasMethodMatching type - * and `tp' has a member matching `pt', or otherwise if - * `tp' is compatible with `pt'. + /** Does type `tp' match expected type `pt' + * This is the case if either `pt' is a unary function type with a + * HasMethodMatching type as result, and `tp' is a unary function + * or method type whose result type has a method whose name and type + * correspond to the HasMethodMatching type, + * or otherwise if `tp' is compatible with `pt'. */ - def matchesPt(tp: Type, pt: Type) = pt match { - case HasMethodMatching(name, argtpes, restpe) => - (tp.member(name) filter (m => isApplicableSafe(undetParams, m.tpe, argtpes, restpe))) != NoSymbol - case _ => - isCompatible(tp, pt) - } + def matchesPt(tp: Type, pt: Type, undet: List[Symbol]) = + isCompatible(tp, pt) || { + pt match { + case Function1(arg, HasMethodMatching(name, argtpes, restpe)) => + normalize(tp) match { + case Function1(arg1, res1) => + (arg <:< arg1) && + (res1.member(name) filter (m => isApplicableSafe(undet, m.tpe, argtpes, restpe))) != NoSymbol + case _ => + false + } + case _ => + false + } + } - if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesWildPt(info.tpe)) - if (isPlausiblyCompatible(info.tpe, wildPt) && matchesWildPt(info.tpe) && isStable(info.pre)) { + if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List())) + if (isPlausiblyCompatible(info.tpe, wildPt) && + matchesPt(depoly(info.tpe), wildPt, List()) && + isStable(info.pre)) { val itree = atPos(tree.pos.focus) { if (info.pre == NoPrefix) Ident(info.name) @@ -408,7 +418,7 @@ self: Analyzer => if (itree2.tpe.isError) SearchFailure else if (hasMatchingSymbol(itree1)) { val tvars = undetParams map freshVar - if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars))) { + if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars), undetParams)) { if (traceImplicits) println("tvars = "+tvars+"/"+(tvars map (_.constr))) val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), false, lubDepth(List(itree2.tpe, pt))) @@ -422,7 +432,7 @@ self: Analyzer => // println("RESULT = "+itree+"///"+itree1+"///"+itree2)//DEBUG result } else { - if (traceImplicits) println("incompatible???") + if (traceImplicits) println("incompatible: "+itree2.tpe+" does not match "+pt.instantiateTypeParams(undetParams, tvars)) SearchFailure } } else if (settings.XlogImplicits.value) |