aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Checking.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-19 19:40:47 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-30 09:51:02 +0200
commit0855b071d913e7acd5271ab34062c69e25cd93cd (patch)
tree471dbd97344a9946e71a20ac80bf0ba59cd3b848 /src/dotty/tools/dotc/typer/Checking.scala
parent035aff45e89084290b8f67ca49007c3eac00f13f (diff)
downloaddotty-0855b071d913e7acd5271ab34062c69e25cd93cd.tar.gz
dotty-0855b071d913e7acd5271ab34062c69e25cd93cd.tar.bz2
dotty-0855b071d913e7acd5271ab34062c69e25cd93cd.zip
Fixes to checkNonCyclic
Simplified logic and now check prefixes of TypeRefs. Without the simplified logic we would get false cyclic errors for ski.scala. Test case: flowops.scala Fixes #1185.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Checking.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala38
1 files changed, 18 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 9b1f756b7..22d2407bc 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -156,16 +156,24 @@ object Checking {
tp
}
- def apply(tp: Type) = tp match {
+ private def apply(tp: Type, cycleOK: Boolean, nestedCycleOK: Boolean): Type = {
+ val savedCycleOK = this.cycleOK
+ val savedNestedCycleOK = this.nestedCycleOK
+ this.cycleOK = cycleOK
+ this.nestedCycleOK = nestedCycleOK
+ try apply(tp)
+ finally {
+ this.cycleOK = savedCycleOK
+ this.nestedCycleOK = savedNestedCycleOK
+ }
+ }
+
+ def apply(tp: Type): Type = tp match {
case tp: TermRef =>
this(tp.info)
mapOver(tp)
case tp @ RefinedType(parent, name) =>
- val parent1 = this(parent)
- val saved = cycleOK
- cycleOK = nestedCycleOK
- try tp.derivedRefinedType(parent1, name, this(tp.refinedInfo))
- finally cycleOK = saved
+ tp.derivedRefinedType(this(parent), name, this(tp.refinedInfo, nestedCycleOK, nestedCycleOK))
case tp @ TypeRef(pre, name) =>
try {
// A prefix is interesting if it might contain (transitively) a reference
@@ -182,19 +190,12 @@ object Checking {
case _: RefinedType => true
case _ => false
}
- // If prefix is interesting, check info of typeref recursively, marking the referred symbol
- // with NoCompleter. This provokes a CyclicReference when the symbol
- // is hit again. Without this precaution we could stackoverflow here.
if (isInteresting(pre)) {
- val info = tp.info
- val sym = tp.symbol
- if (sym.infoOrCompleter == SymDenotations.NoCompleter) throw CyclicReference(sym)
- val symInfo = sym.info
- if (sym.exists) sym.info = SymDenotations.NoCompleter
- try checkInfo(info)
- finally if (sym.exists) sym.info = symInfo
+ val pre1 = this(pre, false, false)
+ checkInfo(tp.info)
+ if (pre1 eq pre) tp else tp.newLikeThis(pre1)
}
- tp
+ else tp
} catch {
case ex: CyclicReference =>
ctx.debuglog(i"cycle detected for $tp, $nestedCycleOK, $cycleOK")
@@ -210,9 +211,6 @@ object Checking {
* @pre sym is not yet initialized (i.e. its type is a Completer).
* @return `info` where every legal F-bounded reference is proctected
* by a `LazyRef`, or `ErrorType` if a cycle was detected and reported.
- * Furthermore: Add an #Apply to a fully instantiated type lambda, if none was
- * given before. This is necessary here because sometimes type lambdas are not
- * recognized when they are first formed.
*/
def checkNonCyclic(sym: Symbol, info: Type, reportErrors: Boolean)(implicit ctx: Context): Type = {
val checker = new CheckNonCyclicMap(sym, reportErrors)(ctx.addMode(Mode.CheckCyclic))