From f1bb72f50da644c439f59e5c6c35e88d6a246f23 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Thu, 23 Sep 2021 11:16:56 +0200 Subject: [PATCH] Fix #13491: Add regression test --- .../test/dotc/pos-test-pickling.blacklist | 1 + tests/pos/13491.scala | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tests/pos/13491.scala diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index e20b5848b40e..7136b2f7ac74 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -37,6 +37,7 @@ i9999.scala 12093.scala 9757.scala 9890.scala +13491.scala # Opaque type i5720.scala diff --git a/tests/pos/13491.scala b/tests/pos/13491.scala new file mode 100644 index 000000000000..d16452cf922c --- /dev/null +++ b/tests/pos/13491.scala @@ -0,0 +1,97 @@ +import scala.annotation.unchecked.uncheckedVariance + +import scala.language.implicitConversions + +sealed trait HList extends Product with Serializable +final case class ::[+H, +T <: HList](head: H, tail: T) extends HList + +sealed trait HNil extends HList +case object HNil extends HNil + +trait HListable[T] { + type Out <: HList +} + +object HListable { + type HL0[T] <: HList = T match { + case Unit => HNil + case HNil => HNil + case ::[a, b] => ::[a, b] + case _ => T :: HNil + } + + implicit def calc[T]: HListable[T] { type Out = HL0[T] } = ??? +} + +sealed trait TailSwitch[L <: HList, T <: HList, R <: HList] { + type Out <: HList +} +object TailSwitch { + type Reverse0[Acc <: HList, L <: HList] <: HList = L match { + case HNil => Acc + case ::[h, t] => Reverse0[h :: Acc, t] + } + + type Reverse1[L <: HList] <: HList = L match { + case HNil => HNil + case ::[h, t] => Reverse0[h :: HNil, t] + } + + type Prepend0[A <: HList, B <: HList] <: HList = A match { + case HNil => B + case ::[h, t] => ::[h, Prepend0[t, B]] + } + + // type-level implementation of this algorithm: + // @tailrec def rec(L, LI, T, TI, R, RI) = + // if (TI <: L) R + // else if (LI <: T) RI.reverse ::: R + // else if (LI <: HNil) rec(L, HNil, T, TI.tail, R, RI) + // else if (TI <: HNil) rec(L, LI.tail, T, HNil, R, LI.head :: RI) + // else rec(L, LI.tail, T, TI.tail, R, LI.head :: RI) + // rec(L, L, T, T, R, HNil) + type TailSwitch0[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList] <: HList = TI match { + case L => R + case _ => + LI match { + case T => Prepend0[Reverse1[RI], R] + case HNil => + TI match { + case ::[_, t] => TailSwitch0[L, HNil, T, t, R, RI] + } + case ::[h, t] => + TI match { + case HNil => TailSwitch0[L, t, T, HNil, R, h :: RI] + case ::[_, tt] => TailSwitch0[L, t, T, tt, R, h :: RI] + } + } + } + + type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out <: HList] = + TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } + + implicit def tailSwitch[L <: HList, T <: HList, R <: HList] + : TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } = ??? +} + +sealed class Rule[-I <: HList, +O <: HList] { + def ~[I2 <: HList, O2 <: HList](that: Rule[I2, O2])(implicit + i: TailSwitch[I2, O@uncheckedVariance, I@uncheckedVariance], + o: TailSwitch[O@uncheckedVariance, I2, O2] + ): Rule[i.Out, o.Out] = ??? + +} +object Rule { + type Rule0 = Rule[HNil, HNil] + type RuleN[+L <: HList] = Rule[HNil, L] + + def rule[I <: HList, O <: HList](r: Rule[I, O]): Rule[I, O] = ??? + implicit def valueMap[T](m: Map[String, T])(implicit h: HListable[T]): RuleN[h.Out] = ??? +} + +object Test { + import Rule._ + val colors: Map[String, Int] = Map("red" -> 1, "green" -> 2, "blue" -> 3) + def EOI: Rule0= ??? + val r = rule(colors ~ EOI) +}