diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index d91649e12edb..3b89d1a20113 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2572,12 +2572,11 @@ class UnknownNamedEnclosingClassOrObject(name: TypeName)(using Context) class IllegalCyclicTypeReference(val ex: CyclicReference, sym: Symbol, where: String, lastChecked: Type)(using Context) extends CyclicMsg(IllegalCyclicTypeReferenceID) { - override def context = "" def msg(using Context) = val lastCheckedStr = try lastChecked.show catch case ex: CyclicReference => "..." - i"illegal cyclic type reference: ${where} ${hl(lastCheckedStr)} of $sym refers back to the type itself" + i"illegal cyclic type reference: ${where} ${hl(lastCheckedStr)} of $sym refers back to the type itself$context" def explain(using Context) = "" } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 621d9ec92d75..f7abdf4bcb1b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -332,8 +332,12 @@ object Checking { || sym.owner.isContainedIn(prefix.cls) // sym reachable through member references ) case prefix: NamedType => - (!sym.is(Private) && prefix.derivesFrom(sym.owner)) || - (!prefix.symbol.moduleClass.isStaticOwner && isInteresting(prefix.prefix)) + !sym.is(Private) && prefix.derivesFrom(sym.owner) + || { + val pcls = prefix.symbol.moduleClass + if pcls.isStaticOwner then pcls.isDefinedInCurrentRun + else isInteresting(prefix.prefix) + } case SuperType(thistp, _) => isInteresting(thistp) case AndType(tp1, tp2) => isInteresting(tp1) || isInteresting(tp2) case OrType(tp1, tp2) => isInteresting(tp1) && isInteresting(tp2) @@ -342,15 +346,27 @@ object Checking { case _ => false } - if (isInteresting(pre)) { - val pre1 = this(pre, false, false) - if (locked.contains(tp) || tp.symbol.infoOrCompleter.isInstanceOf[NoCompleter]) - throw CyclicReference(tp.symbol) - locked += tp - try if (!tp.symbol.isClass) checkInfo(tp.info) - finally locked -= tp - tp.withPrefix(pre1) - } + if isInteresting(pre) then + val traceCycles = CyclicReference.isTraced + try + if traceCycles then + CyclicReference.pushTrace("explore ", tp.symbol, " for cyclic references") + val pre1 = this(pre, false, false) + if locked.contains(tp) + || tp.symbol.infoOrCompleter.isInstanceOf[NoCompleter] + then + throw CyclicReference(tp.symbol) + locked += tp + try + if tp.symbol.isOpaqueAlias then + checkInfo(TypeAlias(tp.translucentSuperType)) + else if !tp.symbol.isClass then + checkInfo(tp.info) + finally + locked -= tp + tp.withPrefix(pre1) + finally + if traceCycles then CyclicReference.popTrace() else tp } catch { @@ -387,7 +403,11 @@ object Checking { */ def checkNonCyclic(sym: Symbol, info: Type, reportErrors: Boolean)(using Context): Type = { val checker = withMode(Mode.CheckCyclic)(new CheckNonCyclicMap(sym, reportErrors)) - try checker.checkInfo(info) + try + val toCheck = info match + case info: RealTypeBounds if sym.isOpaqueAlias => TypeAlias(sym.opaqueAlias) + case _ => info + checker.checkInfo(toCheck) catch { case ex: CyclicReference => if (reportErrors) diff --git a/tests/neg/i15507.check b/tests/neg/i15507.check index 3786d559c306..e31d8966b940 100644 --- a/tests/neg/i15507.check +++ b/tests/neg/i15507.check @@ -1,40 +1,70 @@ --- Error: tests/neg/i15507.scala:2:40 ---------------------------------------------------------------------------------- -2 | type _NestedSet1[X] = Set[_NestedSet1[?]] // error +-- Error: tests/neg/i15507.scala:3:40 ---------------------------------------------------------------------------------- +3 | type _NestedSet1[X] = Set[_NestedSet1[?]] // error | ^ | no wildcard type allowed here --- Error: tests/neg/i15507.scala:3:41 ---------------------------------------------------------------------------------- -3 | type _NestedSet2[X] <: Set[_NestedSet2[?]] // error +-- Error: tests/neg/i15507.scala:4:41 ---------------------------------------------------------------------------------- +4 | type _NestedSet2[X] <: Set[_NestedSet2[?]] // error | ^ | no wildcard type allowed here --- [E140] Cyclic Error: tests/neg/i15507.scala:5:7 --------------------------------------------------------------------- -5 | type _NestedSet4[X] >: Set[_NestedSet4[X]] // error +-- [E140] Cyclic Error: tests/neg/i15507.scala:6:7 --------------------------------------------------------------------- +6 | type _NestedSet4[X] >: Set[_NestedSet4[X]] // error | ^ | illegal cyclic type reference: lower bound ... of type _NestedSet4 refers back to the type itself --- [E140] Cyclic Error: tests/neg/i15507.scala:6:7 --------------------------------------------------------------------- -6 | type _NestedSet5[X] = Set[_NestedSet5[X]] // error + | + | The error occurred while trying to compute the signature of type _NestedSet4 + | which required to explore type _NestedSet4 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i15507.scala:7:7 --------------------------------------------------------------------- +7 | type _NestedSet5[X] = Set[_NestedSet5[X]] // error | ^ | illegal cyclic type reference: alias ... of type _NestedSet5 refers back to the type itself --- [E140] Cyclic Error: tests/neg/i15507.scala:7:7 --------------------------------------------------------------------- -7 | type _NestedSet6[X] = Set[_NestedSet6[Int]] // error + | + | The error occurred while trying to compute the signature of type _NestedSet5 + | which required to explore type _NestedSet5 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i15507.scala:8:7 --------------------------------------------------------------------- +8 | type _NestedSet6[X] = Set[_NestedSet6[Int]] // error | ^ | illegal cyclic type reference: alias ... of type _NestedSet6 refers back to the type itself --- Error: tests/neg/i15507.scala:9:43 ---------------------------------------------------------------------------------- -9 | type _NestedList1[X] = List[_NestedList1[?]] // error - | ^ - | no wildcard type allowed here --- Error: tests/neg/i15507.scala:10:44 --------------------------------------------------------------------------------- -10 | type _NestedList2[X] <: List[_NestedList2[?]] // error + | + | The error occurred while trying to compute the signature of type _NestedSet6 + | which required to explore type _NestedSet6 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- Error: tests/neg/i15507.scala:10:43 --------------------------------------------------------------------------------- +10 | type _NestedList1[X] = List[_NestedList1[?]] // error + | ^ + | no wildcard type allowed here +-- Error: tests/neg/i15507.scala:11:44 --------------------------------------------------------------------------------- +11 | type _NestedList2[X] <: List[_NestedList2[?]] // error | ^ | no wildcard type allowed here --- [E140] Cyclic Error: tests/neg/i15507.scala:12:7 -------------------------------------------------------------------- -12 | type _NestedList4[X] >: List[_NestedList4[X]] // error +-- [E140] Cyclic Error: tests/neg/i15507.scala:13:7 -------------------------------------------------------------------- +13 | type _NestedList4[X] >: List[_NestedList4[X]] // error | ^ | illegal cyclic type reference: lower bound ... of type _NestedList4 refers back to the type itself --- [E140] Cyclic Error: tests/neg/i15507.scala:13:7 -------------------------------------------------------------------- -13 | type _NestedList5[X] = List[_NestedList5[X]] // error + | + | The error occurred while trying to compute the signature of type _NestedList4 + | which required to explore type _NestedList4 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i15507.scala:14:7 -------------------------------------------------------------------- +14 | type _NestedList5[X] = List[_NestedList5[X]] // error | ^ | illegal cyclic type reference: alias ... of type _NestedList5 refers back to the type itself --- [E140] Cyclic Error: tests/neg/i15507.scala:14:7 -------------------------------------------------------------------- -14 | type _NestedList6[X] = List[_NestedList6[Int]] // error + | + | The error occurred while trying to compute the signature of type _NestedList5 + | which required to explore type _NestedList5 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i15507.scala:15:7 -------------------------------------------------------------------- +15 | type _NestedList6[X] = List[_NestedList6[Int]] // error | ^ | illegal cyclic type reference: alias ... of type _NestedList6 refers back to the type itself + | + | The error occurred while trying to compute the signature of type _NestedList6 + | which required to explore type _NestedList6 for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. diff --git a/tests/neg/i15507.scala b/tests/neg/i15507.scala index f65d216ba6a2..98815756df8a 100644 --- a/tests/neg/i15507.scala +++ b/tests/neg/i15507.scala @@ -1,3 +1,4 @@ +//> using options -explain-cyclic object TestNested: type _NestedSet1[X] = Set[_NestedSet1[?]] // error type _NestedSet2[X] <: Set[_NestedSet2[?]] // error diff --git a/tests/neg/i19372.check b/tests/neg/i19372.check new file mode 100644 index 000000000000..94522a5be329 --- /dev/null +++ b/tests/neg/i19372.check @@ -0,0 +1,50 @@ +-- [E140] Cyclic Error: tests/neg/i19372.scala:3:7 --------------------------------------------------------------------- +3 | type AAA = List[bar.BBB] // error: cyclic + | ^ + | illegal cyclic type reference: alias List[Test1.bar.BBB] of type AAA refers back to the type itself + | + | The error occurred while trying to compute the signature of type AAA + | which required to explore type BBB for cyclic references + | which required to explore type AAA for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i19372.scala:9:7 --------------------------------------------------------------------- +9 | type A = bar.B // error: cyclic + | ^ + | illegal cyclic type reference: alias Test2.bar.B of type A refers back to the type itself + | + | The error occurred while trying to compute the signature of type A + | which required to explore type B for cyclic references + | which required to explore type A for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i19372.scala:15:7 -------------------------------------------------------------------- +15 | type AAA = List[bar.BBB] // error: cyclic + | ^ + | illegal cyclic type reference: alias List[Test3.bar.BBB] of type AAA refers back to the type itself + | + | The error occurred while trying to compute the signature of type AAA + | which required to explore type BBB for cyclic references + | which required to explore type AAA for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i19372.scala:21:7 -------------------------------------------------------------------- +21 | type A = bar.B // error: cyclic + | ^ + | illegal cyclic type reference: alias Test4.bar.B of type A refers back to the type itself + | + | The error occurred while trying to compute the signature of type A + | which required to explore type B for cyclic references + | which required to explore type A for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E140] Cyclic Error: tests/neg/i19372.scala:30:7 -------------------------------------------------------------------- +30 | type UCharIteratorReserved = Ptr[UCharIterator] // error: cyclic + | ^ + |illegal cyclic type reference: alias Ptr[structs.UCharIterator] of type UCharIteratorReserved refers back to the type itself + | + |The error occurred while trying to compute the signature of type UCharIteratorReserved + | which required to explore type UCharIterator for cyclic references + | which required to explore type UCharIteratorReserved for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. diff --git a/tests/neg/i19372.scala b/tests/neg/i19372.scala new file mode 100644 index 000000000000..84f460e373f2 --- /dev/null +++ b/tests/neg/i19372.scala @@ -0,0 +1,38 @@ +//> using options -explain-cyclic +object Test1: + type AAA = List[bar.BBB] // error: cyclic + def foo: AAA = ??? + object bar: + opaque type BBB = AAA + +object Test2: + type A = bar.B // error: cyclic + def foo: A = ??? + object bar: + opaque type B = A + +object Test3: + type AAA = List[bar.BBB] // error: cyclic + def foo: AAA = ??? + object bar: + type BBB = AAA + +object Test4: + type A = bar.B // error: cyclic + def foo: A = ??? + object bar: + type B = A + +trait Ptr[T] + +object aliases: + import structs.* + type UCharIteratorReserved = Ptr[UCharIterator] // error: cyclic + object UCharIteratorReserved: + def iterator: UCharIterator = ??? + +object structs: + import aliases.{*, given} + opaque type UCharIterator = Ptr[UCharIteratorReserved] + object UCharIterator: + def reservedFn: UCharIteratorReserved = ??? \ No newline at end of file diff --git a/tests/neg/i8984.scala b/tests/neg/i8984.scala index ff798d803ba3..d31fa45db6e2 100644 --- a/tests/neg/i8984.scala +++ b/tests/neg/i8984.scala @@ -1,12 +1,12 @@ import scala.annotation.tailrec type |@[F[+_], G[+_]] = [a] =>> F[a] | G[a] -object Fix: +object Fix: // error opaque type T[+F[+_]] = ApplyFix.T[F] - def apply[F[+_]](f: F[Fix[F]]): T[F] = ApplyFix(f) + def apply[F[+_]](f: F[Fix[F]]): T[F] = ApplyFix(f) // error // error - extension [F[+_]](fix: T[F]) + extension [F[+_]](fix: T[F]) // error def value: F[Fix[F]] = ApplyFix.unwrap(fix) object ApplyFix: @@ -18,44 +18,3 @@ object Fix: type Fix[+F[+_]] = Fix.T[F] -final case class Cat[+R](name: String, fur: String, rest: R) -object Cat: - def of[R, F[+_]](name: String, fur: String, rest: Fix[F]): Fix[F |@ Cat] = Fix(new Cat(name, fur, rest)) - -final case class Dog[+R](name: String, size: Long, rest: R) -object Dog: - def of[R, F[+_]](name: String, size: Long, rest: Fix[F]): Fix[F |@ Dog] = Fix(new Dog(name, size, rest)) - -case object End: - type f[+a] = End.type - def apply() = Fix[f](End) - -object DropRed: - @tailrec def dropRedCats[F[+a] >: Cat[a]](cats: Fix[F]): Fix[F] = - cats.value match - case Cat(_, "red", rest) => dropRedCats(rest) // error - case _ => cats - - type CatDogVector = Vector[Either[Cat[Unit], Dog[Unit]]] - type CatOrDogs[+a] = Cat[a] | Dog[a] | End.type - - extension (catDogs: Fix[CatOrDogs]) def toVector : CatDogVector = - @tailrec def go(acc: CatDogVector, catDogs: Fix[CatOrDogs]) : CatDogVector = catDogs.value match - case Cat(name, fur, rest) => go(acc :+ Left(Cat(name, fur, ())), rest) - case Dog(name, size, rest) => go(acc :+ Right(Dog(name, size, ())), rest) - case End => acc - - go(Vector(), catDogs) - - val x = - Cat.of("lilly" , "red" , - Cat.of("anya" , "red" , - Cat.of("boris" , "black", - Dog.of("mashka", 3 , - Cat.of("manya" , "red" , - End()))))) - - - def main(args: Array[String]) = - println(x.toVector) - println(dropRedCats(x).toVector)