Skip to content

Commit

Permalink
Only set AppliedType#validSuper after AppliedType#cachedSuper
Browse files Browse the repository at this point in the history
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
  • Loading branch information
EugeneFlesselle committed Jun 11, 2024
1 parent 33b7644 commit e2dfea3
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4646,18 +4646,18 @@ object Types extends TypeUtils {

override def superType(using Context): Type =
if ctx.period != validSuper then
validSuper = if (tycon.isProvisional) Nowhere else ctx.period
var superIsProvisional = tycon.isProvisional
cachedSuper = tycon match
case tycon: HKTypeLambda => defn.AnyType
case tycon: TypeRef if tycon.symbol.isClass => tycon
case tycon: TypeProxy =>
if validSuper != Nowhere && args.exists(_.isProvisional) then
superIsProvisional ||= args.exists(_.isProvisional)
// applyIfParameterized may perform eta-reduction leading to different
// variance annotations depending on the instantiation of type params
// see tests/pos/typeclass-encoding3b.scala:348 for an example
validSuper = Nowhere
tycon.superType.applyIfParameterized(args)
case _ => defn.AnyType
validSuper = if superIsProvisional then Nowhere else ctx.period
cachedSuper

override def translucentSuperType(using Context): Type = tycon match {
Expand Down
22 changes: 22 additions & 0 deletions tests/neg/i20546.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import NamedTuple.{NamedTuple, AnyNamedTuple}

type And[X <: Boolean, Y <: Boolean] <: Boolean = (X, Y) match
case (true, true) => true
case _ => false
type AndLambda = [X <: Boolean, Y <: Boolean] =>> And[X, Y]

trait Expr2[Result, Scalar <: Boolean]:
type StripScalar[E] = E match
case Expr2[_, s] => s

type AllScalar[A <: AnyNamedTuple] = Tuple.Fold[Tuple.Map[NamedTuple.DropNames[A], StripScalar], true, AndLambda] // error: cyclic


object Minimization:
type And[X <: Boolean, Y <: Boolean] = (X, Y) match
case (true, true) => true
case _ => false

type AndLambda = [X <: Boolean, Y <: Boolean] =>> And[X, Y]

type All[A <: Tuple] = Tuple.Fold[A, true, AndLambda] // error: cyclic

0 comments on commit e2dfea3

Please sign in to comment.