Skip to content

Commit 327ecc2

Browse files
authored
Merge pull request #15508 from dotty-staging/fix-cyclic
2 parents f92ab11 + 030e867 commit 327ecc2

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

+3
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,9 @@ object SymDenotations {
658658
containsOpaques ||
659659
is(Module, butNot = Package) && owner.seesOpaques
660660

661+
def isProvisional(using Context): Boolean =
662+
flagsUNSAFE.is(Provisional) // do not force the info to check the flag
663+
661664
/** Is this the denotation of a self symbol of some class?
662665
* This is the case if one of two conditions holds:
663666
* 1. It is the symbol referred to in the selfInfo part of the ClassInfo

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import SymDenotations.LazyType
99
import Decorators._
1010
import util.Stats._
1111
import Names._
12-
import Flags.Module
12+
import Flags.{Module, Provisional}
1313
import dotty.tools.dotc.config.Config
1414

1515
object TypeApplications {
@@ -284,7 +284,8 @@ class TypeApplications(val self: Type) extends AnyVal {
284284

285285
/** Dealias type if it can be done without forcing the TypeRef's info */
286286
def safeDealias(using Context): Type = self match {
287-
case self: TypeRef if self.denot.exists && self.symbol.isAliasType =>
287+
case self: TypeRef
288+
if self.denot.exists && self.symbol.isAliasType && !self.symbol.isProvisional =>
288289
self.superType.stripTypeVar.safeDealias
289290
case _ =>
290291
self

compiler/src/dotty/tools/dotc/core/Types.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ object Types {
118118
case t: TypeRef =>
119119
!t.currentSymbol.isStatic && {
120120
(t: Type).mightBeProvisional = false // break cycles
121-
t.symbol.flagsUNSAFE.is(Provisional)
121+
t.symbol.isProvisional
122122
|| test(t.prefix, theAcc)
123123
|| t.denot.infoOrCompleter.match
124124
case info: LazyType => true

compiler/src/dotty/tools/dotc/typer/Typer.scala

+11-4
Original file line numberDiff line numberDiff line change
@@ -2027,12 +2027,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20272027
var checkedArgs = preCheckKinds(args1, paramBounds)
20282028
// check that arguments conform to bounds is done in phase PostTyper
20292029
val tycon = tpt1.symbol
2030-
if (tycon == defn.andType)
2031-
checkedArgs = checkedArgs.mapconserve(arg =>
2032-
checkSimpleKinded(checkNoWildcard(arg)))
2033-
else if (tycon == defn.orType)
2030+
if tycon == defn.andType || tycon == defn.orType then
20342031
checkedArgs = checkedArgs.mapconserve(arg =>
20352032
checkSimpleKinded(checkNoWildcard(arg)))
2033+
else if tycon.isProvisional then
2034+
// A type with Provisional flag is either an alias or abstract type.
2035+
// If it is an alias type, it would mean the type is cyclic
2036+
// If it is an abstract type, it would mean the type is an irreducible
2037+
// application of a higher-kinded type to a wildcard argument.
2038+
// Either way, the wildcard argument is illegal. The early test of
2039+
// `checkNoWildcard` here is needed, so that we do not accidentally reduce
2040+
// an application of a Provisional type away, which would mean that the type constructor
2041+
// is no longer present on the right hand side. See neg/i15507.scala.
2042+
checkedArgs = checkedArgs.mapconserve(checkNoWildcard)
20362043
else if tycon == defn.throwsAlias
20372044
&& checkedArgs.length == 2
20382045
&& checkedArgs(1).tpe.derivesFrom(defn.RuntimeExceptionClass)

tests/neg/i15507.scala

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object TestNested:
2+
type _NestedSet1[X] = Set[_NestedSet1[?]] // error // error
3+
type _NestedSet2[X] <: Set[_NestedSet2[?]] // error
4+
type _NestedSet3[X] <: Set[_NestedSet3[X]] // ok
5+
type _NestedSet4[X] >: Set[_NestedSet4[X]] // error
6+
type _NestedSet5[X] = Set[_NestedSet5[X]] // error
7+
type _NestedSet6[X] = Set[_NestedSet6[Int]] // error
8+
9+
type _NestedList1[X] = List[_NestedList1[?]] // error // error
10+
type _NestedList2[X] <: List[_NestedList2[?]] // error
11+
type _NestedList3[X] <: List[_NestedList3[X]] // ok
12+
type _NestedList4[X] >: List[_NestedList4[X]] // error
13+
type _NestedList5[X] = List[_NestedList5[X]] // error
14+
type _NestedList6[X] = List[_NestedList6[Int]] // error
15+

0 commit comments

Comments
 (0)