aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-16 18:20:39 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-16 18:20:39 +0100
commite3bc2e9abc9e1749de2cf4ab899d4cb31594869e (patch)
tree115f62c2d174479d191204001fe59e4a80e0ecbb /src/dotty/tools/dotc
parentef09dd258e91bd83100edae267ffa656461d7bc5 (diff)
downloaddotty-e3bc2e9abc9e1749de2cf4ab899d4cb31594869e.tar.gz
dotty-e3bc2e9abc9e1749de2cf4ab899d4cb31594869e.tar.bz2
dotty-e3bc2e9abc9e1749de2cf4ab899d4cb31594869e.zip
Generalize implicit scope of ThisType
The implicit scope of a ThisType is now always the implicit scope of the self type. This caused cycles which necessitated cycle detectors in namedParts and computeImplicitScope.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala38
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala37
2 files changed, 45 insertions, 30 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 4e961ecd9..b3d33e358 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2325,22 +2325,28 @@ object Types {
class NamedPartsAccumulator(p: NamedType => Boolean)(implicit ctx: Context) extends TypeAccumulator[mutable.Set[NamedType]] {
def maybeAdd(x: mutable.Set[NamedType], tp: NamedType) = if (p(tp)) x += tp else x
- def apply(x: mutable.Set[NamedType], tp: Type): mutable.Set[NamedType] = tp match {
- case tp: TermRef =>
- apply(foldOver(maybeAdd(x, tp), tp), tp.underlying)
- case tp: TypeRef =>
- foldOver(maybeAdd(x, tp), tp)
- case tp: ThisType =>
- apply(x, if (tp.cls is Module) tp.underlying else tp.cls.typeRef)
- case tp: ConstantType =>
- apply(x, tp.underlying)
- case tp: MethodParam =>
- apply(x, tp.underlying)
- case tp: PolyParam =>
- apply(x, tp.underlying)
- case _ =>
- foldOver(x, tp)
- }
+ val seen: mutable.Set[Type] = mutable.Set()
+ def apply(x: mutable.Set[NamedType], tp: Type): mutable.Set[NamedType] =
+ if (seen contains tp) x
+ else {
+ seen += tp
+ tp match {
+ case tp: TermRef =>
+ apply(foldOver(maybeAdd(x, tp), tp), tp.underlying)
+ case tp: TypeRef =>
+ foldOver(maybeAdd(x, tp), tp)
+ case tp: ThisType =>
+ apply(x, tp.underlying)
+ case tp: ConstantType =>
+ apply(x, tp.underlying)
+ case tp: MethodParam =>
+ apply(x, tp.underlying)
+ case tp: PolyParam =>
+ apply(x, tp.underlying)
+ case _ =>
+ foldOver(x, tp)
+ }
+ }
}
// ----- Name Filters --------------------------------------------------
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 2c3914800..5ab40d529 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -182,6 +182,8 @@ trait ImplicitRunInfo { self: RunInfo =>
*/
def implicitScope(tp: Type, liftingCtx: Context): OfTypeImplicits = {
+ val seen: mutable.Set[Type] = mutable.Set()
+
/** Replace every typeref that does not refer to a class by a conjunction of class types
* that has the same implicit scope as the original typeref. The motivation for applying
* this map is that it reduces the total number of types for which we need to
@@ -204,21 +206,28 @@ trait ImplicitRunInfo { self: RunInfo =>
}
}
+ def iscopeRefs(tp: Type): TermRefSet =
+ if (seen contains tp) EmptyTermRefSet
+ else {
+ seen += tp
+ iscope(tp).companionRefs
+ }
+
// todo: compute implicits directly, without going via companionRefs?
- def computeImplicitScope(tp: Type): OfTypeImplicits = track("computeImplicicScope") {
- ctx.traceIndented(implicits, i"computeImplicitScope($tp)") {
+ def collectCompanions(tp: Type): TermRefSet = track("computeImplicicScope") {
+ ctx.traceIndented(implicits, i"collectCompanions($tp)") {
val comps = new TermRefSet
tp match {
case tp: NamedType =>
val pre = tp.prefix
- comps ++= iscope(pre).companionRefs
+ comps ++= iscopeRefs(pre)
def addClassScope(cls: ClassSymbol): Unit = {
def addRef(companion: TermRef): Unit =
comps += companion.asSeenFrom(pre, companion.symbol.owner).asInstanceOf[TermRef]
def addParentScope(parent: TypeRef): Unit = {
- iscope(parent).companionRefs foreach addRef
+ iscopeRefs(parent) foreach addRef
for (param <- parent.typeParams)
- comps ++= iscope(pre.member(param.name).info).companionRefs
+ comps ++= iscopeRefs(pre.member(param.name).info)
}
val companion = cls.companionModule
if (companion.exists) addRef(companion.valRef)
@@ -227,24 +236,24 @@ trait ImplicitRunInfo { self: RunInfo =>
tp.classSymbols(liftingCtx) foreach addClassScope
case _ =>
for (part <- tp.namedPartsWith(_.isType))
- comps ++= iscope(part).companionRefs
+ comps ++= iscopeRefs(part)
}
- new OfTypeImplicits(tp, comps)(ctx)
+ comps
}
}
- /** The implicit scope of type `tp`
+ def ofTypeImplicits(comps: TermRefSet) = new OfTypeImplicits(tp, comps)(ctx)
+
+ /** The implicit scope of type `tp`
* @param isLifted Type `tp` is the result of a `liftToClasses` application
*/
def iscope(tp: Type, isLifted: Boolean = false): OfTypeImplicits =
- if (tp.hash == NotCached || !Config.cacheImplicitScopes) computeImplicitScope(tp)
+ if (tp.hash == NotCached || !Config.cacheImplicitScopes)
+ ofTypeImplicits(collectCompanions(tp))
else implicitScopeCache.getOrElseUpdate(tp, {
val liftedTp = if (isLifted) tp else liftToClasses(tp)
- if (liftedTp ne tp) {
- val liftedImplicits = iscope(liftedTp, isLifted = true)
- new OfTypeImplicits(tp, liftedImplicits.companionRefs)(ctx)
- }
- else computeImplicitScope(tp)
+ if (liftedTp ne tp) iscope(liftedTp, isLifted = true)
+ else ofTypeImplicits(collectCompanions(tp))
})
iscope(tp)