diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index ce7e93b51989..9ab49d2f2062 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1548,9 +1548,10 @@ object Types { @tailrec def loop(pre: Type): Type = pre.stripTypeVar match { case pre: RefinedType => pre.refinedInfo match { - case TypeAlias(alias) => - if (pre.refinedName ne name) loop(pre.parent) else alias - case _ => loop(pre.parent) + case tp: AliasingBounds => + if (pre.refinedName ne name) loop(pre.parent) else tp.alias + case _ => + loop(pre.parent) } case pre: RecType => val candidate = pre.parent.lookupRefined(name) @@ -4640,7 +4641,7 @@ object Types { myRepr.nn } - override def toString: String = s"Skolem($hashCode)" + override def toString: String = s"SkolemType($hashCode)" } /** A skolem type used to wrap the type of the qualifier of a selection. diff --git a/tests/pos/13491.scala b/tests/pos/13491.scala index b2c7941e15a0..d764494c6048 100644 --- a/tests/pos/13491.scala +++ b/tests/pos/13491.scala @@ -87,7 +87,7 @@ object Rule { def rule[I <: HList, O <: HList](r: Rule[I, O]): Rule[I, O] = ??? - implicit def valueMap[T, Out0 <: HList](m: Map[String, T])(implicit h: HListable[T] { type Out = Out0 }): RuleN[Out0] = ??? + implicit def valueMap[T, Out0 <: HList](m: Map[String, T])(implicit h: HListable[T]): RuleN[h.Out] = ??? } object Test { diff --git a/tests/pos/i14903a.scala b/tests/pos/i14903a.scala new file mode 100644 index 000000000000..9e4e28320987 --- /dev/null +++ b/tests/pos/i14903a.scala @@ -0,0 +1,22 @@ +trait Wrapper[T] { + type Out + } + + type Func[T] = + T match { + case String => Long + case Long => Int + case Int => Float + case Float => Double + case Double => Unit + case Unit => String + } + + implicit def infer[A]: Wrapper[One[A]] { type Out = Func[A] } = ??? + + trait One[A] { + def use(implicit w: Wrapper[One[A]]): One[w.Out] + } + + val x: One[Long] = null + val _ = x.use.use.use.use.use.use.use diff --git a/tests/pos/i14903b.scala b/tests/pos/i14903b.scala new file mode 100644 index 000000000000..cd61a12e858c --- /dev/null +++ b/tests/pos/i14903b.scala @@ -0,0 +1,54 @@ +import annotation.unchecked.uncheckedVariance + +sealed trait HList +sealed trait HNil extends HList +case object HNil extends HNil +case class ::[+H, +T <: HList](head: H, tail: T) extends HList + +type Concat[X <: HList, Y <: HList] <: HList = X match + case HNil => Y + case h :: t => h :: Concat[t, Y] + +/** + * Decompose L into Prefix ++ Suffix if possible +*/ +type StripSuffix[L <: HList, Suffix <: HList] <: Option[HList] = L match + case Suffix => Some[HNil] + case h :: t => StripSuffix[t, Suffix] match + case Some[x] => Some[h :: x] + case _ => None.type + case _ => None.type + +/** + * type-level implementation of this logic: + * Out = + * R if T has a tail of type L + * (L dropRight T) ++ R if L has a tail of type T +*/ +sealed trait TailSwitch[L <: HList, T <: HList, R <: HList]: + type Out <: HList + +object TailSwitch: + type TS[L <: HList, T <: HList, R <: HList] <: HList = + StripSuffix[T, L] match + case Some[_] => R + case _ => StripSuffix[L, T] match + case Some[x] => Concat[x, R] + + implicit def tailSwitch[L <: HList, T <: HList, R <: HList]: (TailSwitch[L, T, R] { + type Out = TS[L, T, R] + }) = new TailSwitch[L, T, R] { type Out = TS[L, T, R] } + +/** + * Rule popping I from stack and pushing back O +*/ +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 Test: + def dot = new Rule[HNil, HNil] {} + def num = new Rule[HNil, Byte :: HNil] {} + def pattern = num ~ dot ~ num ~ dot ~ num ~ dot ~ num // error