summaryrefslogtreecommitdiff
path: root/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-02-17 15:21:03 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-02-17 15:53:20 +1000
commita8ec6c97ea7edbf25ffffe2e798b2deedcd5955f (patch)
treee5070955dd45536a1804606af9d6d380de4c2036 /src/interactive/scala/tools/nsc/interactive/ContextTrees.scala
parent5a89475526fc91f677d7002b6063bef9e549f0cc (diff)
downloadscala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.tar.gz
scala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.tar.bz2
scala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.zip
SI-9153 More complete and stable results for completions
Three items of background are needed to understand this bug. 1. When typechecking an application like `qual.m({stats; expr})`, the argument is typechecked using the formal parameter type of `m` as the expected type. If this fails with a type error located within in `expr`, the typer instead re-typechecks under `ContextMode.ReTyping` without an expected type, and then searches for an implicit adaptation to enable `view(qual).m(args)`. Under this mode, `Typer#typed1` clears the type of incoming trees. 2. The presentation compiler performs targetted operations like type completions by: - typechecking the enclosing tree, registering all typechecker `Context`s created in the process (`registerContext`) - finding the smallest enclosing `Context` around the target position (`doLocateContext`) - Using this context to perform implicit search, which can contribute members to the completion. (`applicableViews` within `interactive.Global#typeMembers`) 3. When verifiying whether or not a candidate implicit is applicable as a view from `F => T`, implicit search typechecks a dummy call of the form `q"candiate(${Ident("<argument>").setType(typeOf[F])})". Now, picture yourself at the nexus of these three storms. In the enclosed test case, we search for completions at: x + 1.<caret> 1. Because the code is incomplete, the application of `Int#+` doesn't typecheck, and the typer also tries to adapt `x` to a method applicable to the re-typechecked argument. 2. This process registers a context with `retypechecking` set to true. (If multiple contexts at the same position are registered, the last one wins.) 3. Implicit search uses this context to typecheck `Predef.Ensuring(<argument>.setType(Int))`, but the argument is promptly stripped of its type and retypechecking fails as there is no definition named `<argument>` in scope. As such, we missed out on extension methods, like `ensuring` in the list of completions. This commit changes the presentation compiler to turn off retyping mode in the context before starting to work with it. (Are the other modes that might cause similar bugs?) Once I made that change, I noticed that the results the enclosed test was not stable. I tracked this down to the use of a `HashMap` to carry the applicable implicit views, together with the way that the presentation compiler removes duplicates. This commit switched to a `LinkedHashMap`.
Diffstat (limited to 'src/interactive/scala/tools/nsc/interactive/ContextTrees.scala')
-rw-r--r--src/interactive/scala/tools/nsc/interactive/ContextTrees.scala6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala
index bf718c27cc..a4cb3efa4f 100644
--- a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala
@@ -55,7 +55,11 @@ trait ContextTrees { self: Global =>
context
}
}
- locateContextTree(contexts, pos) map locateFinestContextTree map (_.context)
+ def sanitizeContext(c: Context): Context = {
+ c.retyping = false
+ c
+ }
+ locateContextTree(contexts, pos) map locateFinestContextTree map (ct => sanitizeContext(ct.context))
}
/** Returns the ContextTree containing `pos`, or the ContextTree positioned just before `pos`,