diff options
-rw-r--r-- | compiler/src/dotty/tools/dotc/config/Config.scala | 4 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/TypeOps.scala | 20 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Types.scala | 6 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala | 26 | ||||
-rw-r--r-- | tests/pos/i1795.scala | 13 |
6 files changed, 62 insertions, 9 deletions
diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 7744a5479..119af9483 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -133,6 +133,8 @@ object Config { */ final val LogPendingFindMemberThreshold = 10 - /** Maximal number of outstanding recursive calls to findMember */ + /** Maximal number of outstanding recursive calls to findMember before backing out + * when findMemberLimit is set. + */ final val PendingFindMemberLimit = LogPendingFindMemberThreshold * 4 } diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 5f9263009..c2a7d7ea6 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -10,7 +10,8 @@ import NameOps._ import Decorators._ import StdNames._ import Annotations._ -import util.SimpleMap +import config.Config +import util.{SimpleMap, Property} import collection.mutable import ast.tpd._ @@ -67,7 +68,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (thiscls.derivesFrom(cls) && pre.baseTypeRef(thiscls).exists) { if (theMap != null && theMap.currentVariance <= 0 && !isLegalPrefix(pre)) { ctx.base.unsafeNonvariant = ctx.runId - AnnotatedType(pre, Annotation(defn.UnsafeNonvariantAnnot, Nil)) + pre match { + case AnnotatedType(_, ann) if ann.symbol == defn.UnsafeNonvariantAnnot => pre + case _ => AnnotatedType(pre, Annotation(defn.UnsafeNonvariantAnnot, Nil)) + } } else pre } @@ -85,13 +89,15 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (sym.isStatic) tp else { val pre1 = asSeenFrom(tp.prefix, pre, cls, theMap) - if (pre1.isUnsafeNonvariant) - pre1.member(tp.name).info match { + if (pre1.isUnsafeNonvariant) { + val safeCtx = ctx.withProperty(TypeOps.findMemberLimit, Some(())) + pre1.member(tp.name)(safeCtx).info match { case TypeAlias(alias) => // try to follow aliases of this will avoid skolemization. return alias case _ => } + } tp.derivedSelect(pre1) } case tp: ThisType => @@ -554,4 +560,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. object TypeOps { @sharable var track = false // !!!DEBUG + + /** When a property with this key is set in a context, it limit the number + * of recursive member searches. If the limit is reached, findMember returns + * NoDenotation. + */ + val findMemberLimit = new Property.Key[Unit] } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index df1e68944..636204f64 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -581,8 +581,12 @@ object Types { { val recCount = ctx.findMemberCount + 1 ctx.findMemberCount = recCount - if (recCount >= Config.LogPendingFindMemberThreshold) + if (recCount >= Config.LogPendingFindMemberThreshold) { ctx.pendingMemberSearches = name :: ctx.pendingMemberSearches + if (ctx.property(TypeOps.findMemberLimit).isDefined && + ctx.findMemberCount > Config.PendingFindMemberLimit) + return NoDenotation + } } //assert(ctx.findMemberCount < 20) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 76f82d8af..57dd1ea20 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -730,7 +730,7 @@ object Parsers { in.token match { case ARROW => functionRest(t :: Nil) - case FORSOME => syntaxError("existential types no longer supported; use a wildcard type or dependent type instead"); t + case FORSOME => syntaxError(ExistentialTypesNoLongerSupported()); t case _ => t } } diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9dda233bf..b55b7e868 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -5,8 +5,7 @@ package diagnostic import dotc.core._ import Contexts.Context, Decorators._, Symbols._, Names._, NameOps._, Types._ -import util.{SourceFile, NoSource} -import util.{SourcePosition, NoSourcePosition} +import util.SourcePosition import config.Settings.Setting import interfaces.Diagnostic.{ERROR, WARNING, INFO} import printing.Highlighting._ @@ -901,4 +900,27 @@ object messages { val msg = hl"trying to define package with same name as `$existing`" val explanation = "" } + + case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) extends Message(34) { + val kind = "Syntax" + val msg = + hl"""|Existential types are no longer supported - + |use a wildcard or dependent type instead""" + val explanation = + hl"""|The use of existential types is no longer supported. + | + |You should use a wildcard or dependent type instead. + | + |For example: + | + |Instead of using ${"forSome"} to specify a type variable + | + |${"List[T forSome { type T }]"} + | + |Try using a wildcard type variable + | + |${"List[_]"} + |""" + } + } diff --git a/tests/pos/i1795.scala b/tests/pos/i1795.scala new file mode 100644 index 000000000..3e8bd1e97 --- /dev/null +++ b/tests/pos/i1795.scala @@ -0,0 +1,13 @@ +sealed trait T1 {type M1} + +case object o1 extends T1 + +sealed trait T2 {type M2} + +case object o2 extends T2 + +class TestX { + type TestT1 <: T1 {type M1 = TestT2} + type TestT2 <: T2 {type M2 = TestT1} + //val x: TestT1 = o1 +} |