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
@@ -479,6 +480,50 @@ program, so it's helpful to extend a new type (namely ``TTaintType``)::
479
480
class Tainted extends TaintType, TTaintedValue {
480
481
}
481
482
483
+
.. _type-unions:
484
+
485
+
Type unions
486
+
***********
487
+
488
+
Type unions are user-defined types that are declared with the keyword ``class``.
489
+
The syntax resembles :ref:`type aliases <type-aliases>`, but with two or more type expressions on the right-hand side.
490
+
491
+
Type unions are used for creating restricted subsets of an existing :ref:`algebraic datatype <algebraic-datatypes>`, by explicitly
492
+
selecting a subset of the branches of that datatype and binding them to a new type.
493
+
Type unions of :ref:`database types <database-types>` are also supported.
494
+
495
+
You can use a type union to give a name to a subset of the branches from an algebraic datatype.
496
+
In some cases, using the type union over the whole algebraic datatype can avoid spurious
497
+
:ref:`recursion <recursion>` in predicates.
498
+
For example, the following construction is legal::
499
+
500
+
newtype InitialValueSource =
501
+
ExplicitInitialization(VarDecl v) { exists(v.getInitializer()) } or
502
+
ParameterPassing(Call c, int pos) { exists(c.getParameter(pos)) } or
503
+
UnknownInitialGarbage(VarDecl v) { not exists(DefiniteInitialization di | v = target(di)) }
504
+
505
+
class DefiniteInitialization = ParameterPassing or ExplicitInitialization;
506
+
507
+
VarDecl target(DefiniteInitialization di) {
508
+
di = ExplicitInitialization(result) or
509
+
exists(Call c, int pos | di = ParameterPassing(c, pos) and
510
+
result = c.getCallee().getFormalArg(pos))
511
+
}
512
+
513
+
However, a similar implementation that restricts ``InitialValueSource`` in a class extension is not valid.
514
+
If we had implemented ``DefiniteInitialization`` as a class extension instead, it would trigger a type test for ``InitialValueSource``. This results in an illegal recursion ``DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization`` since ``UnknownInitialGarbage`` relies on ``DefiniteInitialization``::
515
+
516
+
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
0 commit comments