-
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.
More aggressive reduction of type selection (fixes parboiled2)
Previously, when reducing `a.T` we checked if the type of `a` was a subtype of `RefinedType(.., T, TypeAlias(...))`, now we extend this check to handle refinements where the `info` is a `TypeBounds` where both bounds are equal. This solves two big issues at once: - We can restore tests/pos/13491.scala to its original form from before #13780. The check for abstract types introduced by #13780 for soundness reasons is no longer hit because the type selection is reduced before we get to that point. This is important because parboiled2 relies on this and is therefore currently broken on 3.1.3-RC1 and main (sirthias/parboiled2#365). - This fixes #14903 (slow compilation issue affecting parboiled2) without caching skolems (as in the alternative fix #14909). Again, this is due to the type containing skolem being reducible to a simpler type and therefore cacheable.
- 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 |