Skip to content

Commit

Permalink
[backport] More aggressive reduction of type selection (fixes parboil…
Browse files Browse the repository at this point in the history
…ed2)

This backports scala#14987 which fixes a regression introduced in 3.1.3-RC1 that
prevented parboiled2 from compiling and also fixes a performance issue affecting
parboiled2.
  • Loading branch information
smarter committed Apr 21, 2022
1 parent 3084183 commit 56c6aa9
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
9 changes: 5 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Expand Up @@ -1545,9 +1545,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)
Expand Down Expand Up @@ -4637,7 +4638,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.
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/13491.scala
Expand Up @@ -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 {
Expand Down
22 changes: 22 additions & 0 deletions 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
54 changes: 54 additions & 0 deletions 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

0 comments on commit 56c6aa9

Please sign in to comment.