Skip to content

Commit 04ada79

Browse files
Mark AppliedType cachedSuper valid Nowhere when using provisional args (#20527)
It solves some stale caching issues with `AppliedType#superType` encountered in `neg/typeclass-encoding3` and when introducing more caching for match types in #20268. These were caused by the fact that `appliedTo` may perform eta-reduction leading to different variance annotations depending on the instantiation of type params. There seems to be no significant performance impact from the reduced opportunities for caching.
2 parents 27a3f80 + 81a1184 commit 04ada79

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -4650,7 +4650,13 @@ object Types extends TypeUtils {
46504650
cachedSuper = tycon match
46514651
case tycon: HKTypeLambda => defn.AnyType
46524652
case tycon: TypeRef if tycon.symbol.isClass => tycon
4653-
case tycon: TypeProxy => tycon.superType.applyIfParameterized(args)
4653+
case tycon: TypeProxy =>
4654+
if validSuper != Nowhere && args.exists(_.isProvisional) then
4655+
// applyIfParameterized may perform eta-reduction leading to different
4656+
// variance annotations depending on the instantiation of type params
4657+
// see tests/pos/typeclass-encoding3b.scala:348 for an example
4658+
validSuper = Nowhere
4659+
tycon.superType.applyIfParameterized(args)
46544660
case _ => defn.AnyType
46554661
cachedSuper
46564662

@@ -4678,8 +4684,8 @@ object Types extends TypeUtils {
46784684
*/
46794685
override def underlyingMatchType(using Context): Type =
46804686
if ctx.period != validUnderlyingMatch then
4681-
validUnderlyingMatch = if tycon.isProvisional then Nowhere else ctx.period
46824687
cachedUnderlyingMatch = superType.underlyingMatchType
4688+
validUnderlyingMatch = validSuper
46834689
cachedUnderlyingMatch
46844690

46854691
override def tryNormalize(using Context): Type = tycon.stripTypeVar match {

Diff for: tests/neg/typeclass-encoding3.scala renamed to tests/pos/typeclass-encoding3b.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -345,5 +345,12 @@ object functors {
345345
}
346346

347347
MonadFlatten.flattened(List(List(1, 2, 3), List(4, 5))) // ok, synthesizes (using ListMonad)
348-
MonadFlatten.flattened(List(List(1, 2, 3), List(4, 5)))(using ListMonad) // error
348+
MonadFlatten.flattened(List(List(1, 2, 3), List(4, 5)))(using ListMonad) // was an error
349+
/*
350+
Before the changes, when checking `ListMonad <:< functors.Monad.Impl[T]`
351+
we eventually got to the comparison `[X] =>> T[X] <:< [+X] =>> List[X]`
352+
because the `This` type member of `ListMonad` has a covariance annotation.
353+
This failed the variance conformance checks despite the fact that T had been instantiated to List,
354+
since it had been substituted into the refinement (and cached) before its instantiation.
355+
*/
349356
}

0 commit comments

Comments
 (0)