From 9000ebfc7855ccc142ed1bebd00a8cd6153f6b2e Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 28 Jun 2023 11:04:20 +0100 Subject: [PATCH] Avoid GADT casting with ProtoTypes --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 13 +++++++++++-- tests/pos/i18062.scala | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i18062.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1c00c276376e..a8ba3c31655c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4560,7 +4560,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer AnnotatedType(conj, Annotation(defn.UncheckedStableAnnot, tree.symbol.span)) else conj else pt - gadts.println(i"insert GADT cast from $tree to $target") - tree.cast(target) + if target.existsPart(_.isInstanceOf[ProtoType]) then + // we want to avoid embedding a SelectionProto in a Conversion, as the result type + // as it might end up within a GADT cast type, e.g. tests/pos/i15867.scala + // so we just bail - in that example, a GADT cast will be insert on application, so it compiles. + // but tests/pos/i18062.scala is an example with a polymorphic method, which requires type variables to + // be applied to the tree and then constrained before they match the prototype. + // so rather than try to handle all that before calling adapt, let's just bail on this side. + tree + else + gadts.println(i"insert GADT cast from $tree to $target") + tree.cast(target) end insertGadtCast } diff --git a/tests/pos/i18062.scala b/tests/pos/i18062.scala new file mode 100644 index 000000000000..48863c4349c7 --- /dev/null +++ b/tests/pos/i18062.scala @@ -0,0 +1,14 @@ +trait CB[X] { def get: X } + +trait WrapperConvert[F[_], G[_]]: + def conv[X](fx: F[X]): G[X] + +object WrapperConvert: + implicit def id[F[_]]: WrapperConvert[F, F] = new WrapperConvert[F, F]: + def conv[X](fx: F[X]): F[X] = fx + +transparent inline given convertX[F[_], X](using wc: WrapperConvert[F, CB]): Conversion[F[X], X] = + new Conversion[F[X], X]: + def apply(fx: F[X]) = wc.conv(fx).get + +def test(cb: CB[Int], x: Int): Int = cb + x