summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-12-11 16:08:33 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-12-11 20:06:08 +0100
commit110fde017ee32b7387393dad9b859fd89e900650 (patch)
treedf0be7e74493af0643316b37a950b34e54c214d6 /src/compiler/scala/tools/nsc/typechecker/Contexts.scala
parent0304e00168393d47e18dbb4d2c634d51bab1383a (diff)
downloadscala-110fde017ee32b7387393dad9b859fd89e900650.tar.gz
scala-110fde017ee32b7387393dad9b859fd89e900650.tar.bz2
scala-110fde017ee32b7387393dad9b859fd89e900650.zip
SI-6780 Refactor Context#implicitss
- split out a method for the part concernted with implicits from the current context - leaving the outer code to handle caching, cycle detection, and recursion up the context chain.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Contexts.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala63
1 files changed, 33 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index b7a942fc0d..2b4417a80d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -832,12 +832,11 @@ trait Contexts { self: Analyzer =>
* filtered out later by `eligibleInfos` (SI-4270 / 9129cfe9), as they don't type-check.
*/
def implicitss: List[List[ImplicitInfo]] = {
- val imports = this.imports
val nextOuter = this.nextOuter
def withOuter(is: List[ImplicitInfo]): List[List[ImplicitInfo]] =
is match {
case Nil => nextOuter.implicitss
- case _ => is :: nextOuter.implicitss
+ case _ => is :: nextOuter.implicitss
}
val CycleMarker = NoRunId - 1
@@ -846,38 +845,42 @@ trait Contexts { self: Analyzer =>
withOuter(Nil)
} else if (implicitsRunId != currentRunId) {
implicitsRunId = CycleMarker
- implicitsCache = List()
- var canCache = true
- val newImplicits: List[ImplicitInfo] =
- if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass && !inSelfSuperCall) {
- if (!owner.isInitialized) { canCache = false; Nil }
- else savingEnclClass(this) {
- // !!! In the body of `class C(implicit a: A) { }`, `implicitss` returns `List(List(a), List(a), List(<predef..)))`
- // it handled correctly by implicit search, which considers the second `a` to be shadowed, but should be
- // remedied nonetheless.
- collectImplicits(owner.thisType.implicitMembers, owner.thisType)
- }
- } else if (scope != nextOuter.scope && !owner.isPackageClass) {
- debuglog("collect local implicits " + scope.toList)//DEBUG
- collectImplicits(scope, NoPrefix)
- } else if (firstImport != nextOuter.firstImport) {
- assert(imports.tail.headOption == nextOuter.firstImport, (imports, nextOuter.imports))
- collectImplicitImports(imports.head)
- } else if (owner.isPackageClass) {
- // the corresponding package object may contain implicit members.
- collectImplicits(owner.tpe.implicitMembers, owner.tpe)
- } else List()
-
- if (canCache) {
- implicitsRunId = currentRunId
- implicitsCache = newImplicits
- } else implicitsRunId = NoRunId
-
- withOuter(newImplicits)
+ implicits(nextOuter) match {
+ case None =>
+ implicitsRunId = NoRunId
+ withOuter(Nil)
+ case Some(is) =>
+ implicitsRunId = currentRunId
+ implicitsCache = is
+ withOuter(is)
+ }
}
else withOuter(implicitsCache)
}
+ /** @return None if a cycle is detected, or Some(infos) containing the in-scope implicits at this context */
+ private def implicits(nextOuter: Context): Option[List[ImplicitInfo]] = {
+ val imports = this.imports
+ if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass && !inSelfSuperCall) {
+ if (!owner.isInitialized) None
+ else savingEnclClass(this) {
+ // !!! In the body of `class C(implicit a: A) { }`, `implicitss` returns `List(List(a), List(a), List(<predef..)))`
+ // it handled correctly by implicit search, which considers the second `a` to be shadowed, but should be
+ // remedied nonetheless.
+ Some(collectImplicits(owner.thisType.implicitMembers, owner.thisType))
+ }
+ } else if (scope != nextOuter.scope && !owner.isPackageClass) {
+ debuglog("collect local implicits " + scope.toList)//DEBUG
+ Some(collectImplicits(scope, NoPrefix))
+ } else if (firstImport != nextOuter.firstImport) {
+ assert(imports.tail.headOption == nextOuter.firstImport, (imports, nextOuter.imports))
+ Some(collectImplicitImports(imports.head))
+ } else if (owner.isPackageClass) {
+ // the corresponding package object may contain implicit members.
+ Some(collectImplicits(owner.tpe.implicitMembers, owner.tpe))
+ } else Some(Nil)
+ }
+
//
// Imports and symbol lookup
//