Skip to content

Commit bd25160

Browse files
only cache baseTypes when gadtState is empty
1 parent 1716bcd commit bd25160

File tree

4 files changed

+19
-3
lines changed

4 files changed

+19
-3
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ object Phases {
431431
final def sameParentsStartId: Int = mySameParentsStartId
432432
// id of first phase where all symbols are guaranteed to have the same parents as in this phase
433433
final def sameBaseTypesStartId: Int = mySameBaseTypesStartId
434-
// id of first phase where all symbols are guaranteed to have the same base tpyes as in this phase
434+
// id of first phase where all symbols are guaranteed to have the same base types as in this phase
435435

436436
protected[Phases] def init(base: ContextBase, start: Int, end: Int): Unit = {
437437
if (start >= FirstPhaseId)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2192,7 +2192,8 @@ object SymDenotations {
21922192
Stats.record("basetype cache entries")
21932193
if (!baseTp.exists) Stats.record("basetype cache NoTypes")
21942194
}
2195-
if (!tp.isProvisional && !CapturingType.isUncachable(tp))
2195+
if !(tp.isProvisional || CapturingType.isUncachable(tp) || ctx.gadt.isNarrowing) then
2196+
// NOTE alternative: always try with empty gadt ctx first, can then always use cache, o.w. can try with ctx but no caching
21962197
btrCache(tp) = baseTp
21972198
else
21982199
btrCache.remove(tp) // Remove any potential sentinel value

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4075,7 +4075,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
40754075
case CompareResult.OKwithGADTUsed
40764076
if pt.isValueType
40774077
&& !inContext(ctx.fresh.setGadtState(GadtState(GadtConstraint.empty))) {
4078-
val res = (tree.tpe.widenExpr frozen_<:< pt)
4078+
// tree.tpe.classSymbol.denot.asClass.invalidateBaseTypeCache() // NOTE fixes the issue
4079+
val res = trace(i"unnecessary GADT for $tree: ${tree.tpe.widenExpr} vs $pt in ${ctx.source}"):
4080+
tree.tpe.widenExpr frozen_<:< pt
40794081
if res then
40804082
// we overshot; a cast is not needed, after all.
40814083
gadts.println(i"unnecessary GADTused for $tree: ${tree.tpe.widenExpr} vs $pt in ${ctx.source}")

tests/pos/i19521.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
final abstract class PLet
3+
4+
sealed trait Expr[+P]
5+
case class ELet[+A](name: String, expr: Expr[A]) extends Expr[A | PLet]
6+
7+
def go[P](e: Expr[P]): P = e match
8+
case ELet(_, _) =>
9+
val x: Expr[P] | ELet[P] = ???
10+
val y: Expr[P] = x // conforms iff using gadt constraints
11+
// error before changes: cast from gadt reasoning was not inserted because
12+
// `Expr[P]` was erronously cached as a baseType of `Expr[P] | ELet[P]` (only true with gadt constraints)
13+
???

0 commit comments

Comments
 (0)