You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _posts/2025-12-02-lazier-bdds-for-set-theoretic-types.markdown
+4-22Lines changed: 4 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -277,26 +277,7 @@ The issues we outlined above for intersections are even worse for differences. L
277
277
{a2, B1andnot (C2orU2), :bottom, B1andnot (D2orU2)} when a1 > a2
278
278
```
279
279
280
-
As you can see, all operations shuffle the union nodes and return `:bottom`. But this time, we know how to improve it! Let's start with `a1 == a2`. If we expand the difference in the constrained part, we get:
281
-
282
-
```elixir
283
-
(C1andnotC2andnotU2) or (U1andnotC2andnotU2)
284
-
```
285
-
286
-
If we do the same in the dual part, we have:
287
-
288
-
```elixir
289
-
(D1andnotD2andnotU2) or (U1andnotD2andnotU2)
290
-
```
291
-
292
-
Unfortunately, there are no shared union terms between the constrained and dual parts, unless C2 and D2 are `:bottom`. Therefore, instead of fully rewriting the difference of equal nodes, we add the following special case:
293
-
294
-
```elixir
295
-
{a1, C1andnotU2, U1andnotU2, D1andnotU2}
296
-
when a1 == a2 andC2==:bottomandD2==:bottom
297
-
```
298
-
299
-
We can apply a similar optimization when `a1 < a2`. The current formula:
280
+
As you can see, all operations shuffle the union nodes and return `:bottom`. However, after analyzing each condition carefully, we can apply a similar optimization when `a1 < a2`. The current formula:
300
281
301
282
```elixir
302
283
{a1, (C1orU1) andnotB2, :bottom, (D1orU1) andnotB2} when a1 < a2
@@ -311,13 +292,14 @@ The constrained part can be written as `(C1 and not B2) or (U1 and not B2)` and
311
292
Unfortunately, we can't apply this for `a2 > a1`, as differences are asymmetric and do not distribute over unions on the right side. Therefore, the updated formula for difference is:
312
293
313
294
```elixir
314
-
{a1, C1andnotU2, U1andnotU2, D1andnotU2} when a1 == a2 andC2==:bottomandD2==:bottom
{a1, C1andnotB2, U1andnotB2, D1andnotB2} when a1 < a2
317
297
{a2, B1andnot (C2orU2), :bottom, B1andnot (D2orU2)} when a1 > a2
318
298
```
319
299
320
-
With these new formulas, all new typing features in Elixir v1.19 perform efficiently and most projects now type check faster than in Elixir v1.18. You can derive similar properties when `a1 == a2` and `(U1 == :bottom) or (U1 == U2)`. Give it a try!
300
+
With these new formulas, all new typing features in Elixir v1.19 perform efficiently and most projects now type check faster than in Elixir v1.18.
301
+
302
+
> Note from 2026-03-18: a previous version of this article provided special cases for `a1 == a2` but we noticed it led to a performance degradation in Elixir v1.20, therefore they have been removed from the article. The original formula can be found in Guillaume Duboc's thesis. The formulas above represent the ones found in the Elixir compiler as of the day of this note.
0 commit comments