-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14987 from dotty-staging/aggressive-reduction
More aggressive reduction of type selection (fixes parboiled2)
- Loading branch information
Showing
4 changed files
with
82 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |