-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Milestone
Description
Minimized code
def test[A, B](a: A, b: B): A | B = a
val v0 = test("string", 1)
val v1 = test(1, "string")
val v2 = test(v0, v1)
val v3 = test(v1, v0)
val v4 = test(v2, v3)
val v5 = test(v3, v2)
val v6 = test(v4, v5)
Output
val v0: String | Int = string
val v1: Int | String = 1
val v2: String | Int | (Int | String) = string
val v3: Int | String | (String | Int) = 1
val v4: String | Int | (Int | String) | (Int | String | (String | Int)) = string
val v5: Int | String | (String | Int) | (String | Int | (Int | String)) = 1
val v6: String | Int | (Int | String) | (Int | String | (String | Int)) | (Int | String | (String | Int) | (String | Int | (Int | String))) = string
Expectation
I'd expect all vN values to have type String | Int
. Initially I thought that only printing in the REPL was affected, but compilation time also grows exponentially.
VoytechM, izhangzhihao, He-Pin, TheElectronWill, ysthakur and 5 more
Activity
[-]Union type exponential explosion[/-][+]Deduplicate union types[/+]abgruszecki commentedon Dec 8, 2020
I'd expect our compilation time to be worst-case exponential anyway, this is just another way to trigger worst-case behaviour. I believe one can do similar things with tuples.
Arguably the example is almost abusive, though we clearly could do slightly better when instantiating unions of type parameters.
odersky commentedon Dec 26, 2020
Any concrete ideas how to do better that do not increase compilation times for normal cases?
abgruszecki commentedon Jan 4, 2021
We discussed this during the lab meeting. One thing which seems feasible to do is to "deduplicate" union types when instantiating polymorphic definitions. We could flatten union types, and then compare all union members and remove those that have the same identity. We don't want to do subtype comparisons b/c of perf concerns. The implementation probably should modify the
.simplify
method for simplifying unions.tpolecat commentedon Feb 5, 2021
Another example
griggt commentedon Feb 5, 2021
tpolecat commentedon Feb 5, 2021
ok that is sweet
soronpo commentedon Feb 5, 2021
Maybe the examples should also cover commutative and distributive with
&
.X & Y | Y & X
X & (Y | Z) | (X & Y | X & Z)
johnynek commentedon Feb 6, 2021
In this example: #10693 (comment) we are also missing, what I expect is a law, that
A | Nothing == A
. Similarly,A | Any = Any
.Swoorup commentedon Feb 6, 2021
The line
gives the error
Wonder that should just work too?
20 remaining items