Skip to content

Commit e2dfea3

Browse files
Only set AppliedType#validSuper after AppliedType#cachedSuper
since cycles are possible when computing `AppliedType#superType`, see tests/neg/i20546.scala for an example leading to an NPE. We could use `ctx.period == validSuper && cachedSuper == null` as condition to detect cycles, but they are already handled in `TypeApplications#appliedTo`, with a better error message. We can update `AppliedType#validSuper` only after the computation is done to fix #20546
1 parent 33b7644 commit e2dfea3

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -4646,18 +4646,18 @@ object Types extends TypeUtils {
46464646

46474647
override def superType(using Context): Type =
46484648
if ctx.period != validSuper then
4649-
validSuper = if (tycon.isProvisional) Nowhere else ctx.period
4649+
var superIsProvisional = tycon.isProvisional
46504650
cachedSuper = tycon match
46514651
case tycon: HKTypeLambda => defn.AnyType
46524652
case tycon: TypeRef if tycon.symbol.isClass => tycon
46534653
case tycon: TypeProxy =>
4654-
if validSuper != Nowhere && args.exists(_.isProvisional) then
4654+
superIsProvisional ||= args.exists(_.isProvisional)
46554655
// applyIfParameterized may perform eta-reduction leading to different
46564656
// variance annotations depending on the instantiation of type params
46574657
// see tests/pos/typeclass-encoding3b.scala:348 for an example
4658-
validSuper = Nowhere
46594658
tycon.superType.applyIfParameterized(args)
46604659
case _ => defn.AnyType
4660+
validSuper = if superIsProvisional then Nowhere else ctx.period
46614661
cachedSuper
46624662

46634663
override def translucentSuperType(using Context): Type = tycon match {

Diff for: tests/neg/i20546.scala

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import NamedTuple.{NamedTuple, AnyNamedTuple}
2+
3+
type And[X <: Boolean, Y <: Boolean] <: Boolean = (X, Y) match
4+
case (true, true) => true
5+
case _ => false
6+
type AndLambda = [X <: Boolean, Y <: Boolean] =>> And[X, Y]
7+
8+
trait Expr2[Result, Scalar <: Boolean]:
9+
type StripScalar[E] = E match
10+
case Expr2[_, s] => s
11+
12+
type AllScalar[A <: AnyNamedTuple] = Tuple.Fold[Tuple.Map[NamedTuple.DropNames[A], StripScalar], true, AndLambda] // error: cyclic
13+
14+
15+
object Minimization:
16+
type And[X <: Boolean, Y <: Boolean] = (X, Y) match
17+
case (true, true) => true
18+
case _ => false
19+
20+
type AndLambda = [X <: Boolean, Y <: Boolean] =>> And[X, Y]
21+
22+
type All[A <: Tuple] = Tuple.Fold[A, true, AndLambda] // error: cyclic

0 commit comments

Comments
 (0)