@@ -14,7 +14,8 @@ than one type.
14
14
15
15
The kinds of types in QL are :ref: `primitive types <primitive-types >`, :ref: `classes <classes >`,
16
16
:ref: `character types <character-types >`, :ref: `class domain types <domain-types >`,
17
- :ref: `algebraic datatypes <algebraic-datatypes >`, and :ref: `database types <database-types >`.
17
+ :ref: `algebraic datatypes <algebraic-datatypes >`, :ref: `type unions <type-unions >`,
18
+ and :ref: `database types <database-types >`.
18
19
19
20
.. index :: boolean, float, int, string, date
20
21
.. _primitive-types :
@@ -479,6 +480,44 @@ 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
+ .. note :: The syntax for type unions is considered experimental and is subject to change.
489
+ However, they appear in the `standard QL libraries <https://github.com/github/codeql> `.
490
+ The following sections should help you understand those examples
491
+
492
+ Type unions are user-defined types that are declared with the keyword ``class ``.
493
+ The syntax resembles type aliases, but with two or more type expressions on the right-hand side.
494
+
495
+ Type unions are used for creating restricted versions of existing algebraic datatypes, by explicitly
496
+ selecting a subset of the branches of said datatype and binding them to a new type.
497
+ In addition to this, type unions of database types are also supported.
498
+
499
+ Using a type union to explicitly restrict the permitted branches from an algebraic datatype
500
+ can resolve spurious recursion in predicates.
501
+ For example, the following construction is legal::
502
+
503
+ newtype T =
504
+ T1(T t) { not exists(T2orT3 s | t = s) } or
505
+ T2(int x) { x = 1 or x = 2 } or
506
+ T3(int x) { x = 3 or x = 4 or x = 5 }
507
+
508
+ class T2orT3 = T2 or T3;
509
+
510
+ However, a similar implementation that restricts ``T `` in a class extension is not valid.
511
+ The class ``T2orT3 `` triggers a type test for ``T ``, which results in an illegal recursion
512
+ ``T2orT3->T->T1->¬T2orT2 `` due to the reliance of ``T1 `` on ``T2orT3 ``::
513
+
514
+ class T2orT3 extends T {
515
+ T2orT3() {
516
+ this instanceof T2 or this instanceof T3
517
+ }
518
+ // ...
519
+ }
520
+
482
521
.. _database-types :
483
522
484
523
Database types
0 commit comments