From 5a6f7e7ed5913dad816a6a808dd1a64aaf4f2598 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 27 Jun 2022 20:13:00 +0800 Subject: [PATCH] avoid leaking internal types in GadtConstraint.approximation --- .../src/dotty/tools/dotc/core/GadtConstraint.scala | 10 +++++++++- tests/pos/i15531.scala | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i15531.scala diff --git a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala index 6861b30fbc00..7949f87e4e55 100644 --- a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala @@ -209,7 +209,15 @@ final class ProperGadtConstraint private( def isNarrowing: Boolean = wasConstrained override def approximation(sym: Symbol, fromBelow: Boolean)(using Context): Type = { - val res = approximation(tvarOrError(sym).origin, fromBelow = fromBelow) + val res = + approximation(tvarOrError(sym).origin, fromBelow = fromBelow) match + case tpr: TypeParamRef => + // Here we do externalization when the returned type is a TypeParamRef, + // b/c ConstraintHandling.approximation may return internal types when + // the type variable is instantiated. See #15531. + externalize(tpr) + case tp => tp + gadts.println(i"approximating $sym ~> $res") res } diff --git a/tests/pos/i15531.scala b/tests/pos/i15531.scala new file mode 100644 index 000000000000..72a42dc5ed9f --- /dev/null +++ b/tests/pos/i15531.scala @@ -0,0 +1,9 @@ +trait Tag { val data: Int } + +enum EQ[A, B]: + case Refl[C]() extends EQ[C, C] + +def foo[T, B <: Tag](ev: EQ[T, B], x: T) = ev match + case EQ.Refl() => + val i: Int = x.data +