summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-08-11 21:54:11 +0200
committerEugene Burmako <xeno.by@gmail.com>2013-10-11 13:03:49 +0200
commit210dbc7887bc42eed4154de65d0ff5f46ca5ee58 (patch)
tree535e273511e0503a743a14fad7099d9fa73ac04c /src
parentacd77803f7da7c369f4ffdc70b5eeec4a23e35ae (diff)
downloadscala-210dbc7887bc42eed4154de65d0ff5f46ca5ee58.tar.gz
scala-210dbc7887bc42eed4154de65d0ff5f46ca5ee58.tar.bz2
scala-210dbc7887bc42eed4154de65d0ff5f46ca5ee58.zip
SI-3346 implicit parameters can now guide implicit view inference
This simple patch makes it possible for implicit views to benefit from fundep-guided type inference, eliminating a nasty special case in implicit inference. Here are the changes that I had to apply to the tests (they exposed quite a number of interesting questions that I was happy to answer): 1) neg/t5845.scala now works, so I moved it to pos. That easily makes sense, because the test was just a canary to track previous state of things. 2) neg/divergent_implicit.scala, neg/t5578.scala and neg/t7519.scala changed their messages to less informative ones, because inapplicable implicit views now get disqualified early and therefore don't display their error messages to the user. This is an unfortunate but necessary byproduct of this change, and one can argue that the behavior is now completely consistent with implicit vals (that also don't explain why this or that implicit val got disqualified, but rather display a generic implicit value not found message). 3) scaladoc/implicits-chaining.scala and scaladoc/implicits-base.scala. Immediate culling of apriori inapplicable implicit views messes things up for Scaladoc, because it's interested in potentially applicable views, having infrastructure to track various constraints (type bounds, requirements for implicit parameters, etc) that guide applicability of views and then present it to the user. Therefore, when scaladoc is detected, implicit search reverts to the old behavior. 4) We still cannot have Jason's workaround to type constructor inference mentioned in comments to SI-3346, because it's not really about implicit parameters of implicit views, but about type inference flowing from the implicit parameter list to a preceding parameter list in order to affect inference of an implicit view. This is something that's still too ambitious.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index b30ae917d9..c19d861d23 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -579,10 +579,10 @@ trait Implicits {
private def typedImplicit1(info: ImplicitInfo, isLocal: Boolean): SearchResult = {
if (Statistics.canEnable) Statistics.incCounter(matchingImplicits)
- val itree = atPos(pos.focus) {
- // workaround for deficient context provided by ModelFactoryImplicitSupport#makeImplicitConstraints
- val isScalaDoc = context.tree == EmptyTree
+ // workaround for deficient context provided by ModelFactoryImplicitSupport#makeImplicitConstraints
+ val isScalaDoc = context.tree == EmptyTree
+ val itree = atPos(pos.focus) {
if (isLocal && !isScalaDoc) {
// SI-4270 SI-5376 Always use an unattributed Ident for implicits in the local scope,
// rather than an attributed Select, to detect shadowing.
@@ -605,7 +605,23 @@ trait Implicits {
atPos(itree.pos)(Apply(itree, List(Ident("<argument>") setType approximate(arg1)))),
EXPRmode,
approximate(arg2)
- )
+ ) match {
+ // try to infer implicit parameters immediately in order to:
+ // 1) guide type inference for implicit views
+ // 2) discard ineligible views right away instead of risking spurious ambiguous implicits
+ //
+ // this is an improvement of the state of the art that brings consistency to implicit resolution rules
+ // (and also helps fundep materialization to be applicable to implicit views)
+ //
+ // there's one caveat though. we need to turn this behavior off for scaladoc
+ // because scaladoc usually doesn't know the entire story
+ // and is just interested in views that are potentially applicable
+ // for instance, if we have `class C[T]` and `implicit def conv[T: Numeric](c: C[T]) = ???`
+ // then Scaladoc will give us something of type `C[T]`, and it would like to know
+ // that `conv` is potentially available under such and such conditions
+ case tree if isImplicitMethodType(tree.tpe) && !isScalaDoc => applyImplicitArgs(tree)
+ case tree => tree
+ }
case _ => fallback
}
context.firstError match { // using match rather than foreach to avoid non local return.
@@ -617,7 +633,7 @@ trait Implicits {
if (Statistics.canEnable) Statistics.incCounter(typedImplicits)
- val itree2 = if (isView) (itree1: @unchecked) match { case Apply(fun, _) => fun }
+ val itree2 = if (isView) treeInfo.dissectApplied(itree1).callee
else adapt(itree1, EXPRmode, wildPt)
typingStack.showAdapt(itree, itree2, pt, context)