@@ -17,7 +17,7 @@ For example, to declare a module ``M`` as private, you could use:
1717
1818 Note that some annotations act on an entity itself, whilst others act on a particular *name * for the entity:
1919 - Act on an **entity **: ``abstract ``, ``bindingset ``, ``cached ``, ``extensible ``, ``external ``, ``language ``,
20- ``override ``, ``pragma ``, and ``transient ``
20+ ``overlay ``, `` override ``, ``pragma ``, and ``transient ``
2121 - Act on a **name **: ``additional ``, ``deprecated ``, ``final ``, ``library ``, ``private ``, and ``query ``
2222
2323For example, if you annotate an entity with ``private ``, then only that particular name is
@@ -502,6 +502,193 @@ The ``bindingset`` annotation takes a comma-separated list of variables.
502502 For more information, see ":ref: `predicate-binding `."
503503- When you annotate a class, each variable must be ``this `` or a field in the class.
504504
505+ .. _overlay :
506+
507+ Overlay annotations
508+ ===================
509+
510+ Overlay annotations control how predicates behave during **overlay evaluation **, a feature
511+ that enables efficient incremental analysis of codebases.
512+
513+ In overlay evaluation, a *base database * is created from one version of a codebase, and an
514+ *overlay database * is created by combining the base database with changes from a newer
515+ version (such as a pull request). The goal is to analyze the overlay database as if it
516+ were a fully extracted database at the newer commit, while reusing as much cached data
517+ from the base database as possible. Ideally, analysis time is proportional to the size
518+ of the diff rather than the full codebase.
519+
520+ To achieve this, predicates are divided into *local * and *global * categories, with global
521+ being the default. Local predicates are evaluated independently on base and overlay data,
522+ and thus typically take time proportional to the diff size; global predicates operate on
523+ the combined data, and thus take time proportional to the full codebase. When a global
524+ predicate calls a local predicate, results from both the base and overlay evaluations of
525+ the local predicate are combined, with stale base results filtered out through a process
526+ called "discarding".
527+
528+ Overlay evaluation is primarily used internally by GitHub Code Scanning to speed up
529+ pull request analysis. Most QL developers do not need to use these annotations directly,
530+ but understanding them can help resolve compilation errors that may occur when overlay
531+ support is enabled for a language.
532+
533+ .. note ::
534+
535+ Overlay annotations only affect evaluation when overlay compilation is enabled
536+ (via ``compileForOverlayEval: true `` in ``qlpack.yml ``) and the evaluator is running
537+ in overlay mode. This setting is typically only needed in the language's library pack;
538+ custom query packs do not need it. Outside of overlay mode, these annotations are
539+ validated but have no effect on evaluation.
540+
541+ ``overlay[local] ``
542+ ------------------
543+
544+ **Available for **: |modules |, |classes |, |algebraic datatypes |, |type unions |, |characteristic predicates |, |member predicates |, |non-member predicates |
545+
546+ The ``overlay[local] `` annotation declares that a predicate is local. Local predicates are
547+ evaluated separately on base and overlay data and may only depend on other local predicates.
548+ The compiler reports an error if a local predicate depends on a global predicate.
549+
550+ .. code-block :: ql
551+
552+ // All dependencies are database extensionals, so this can be local
553+ overlay[local]
554+ predicate stmtInFile(@stmt s, string path) {
555+ exists(@file f, @location loc |
556+ hasLocation(s, loc) and
557+ locations_default(loc, f, _, _, _, _) and
558+ files(f, path)
559+ )
560+ }
561+
562+ ``overlay[local?] ``
563+ -------------------
564+
565+ **Available for **: |modules |, |classes |, |algebraic datatypes |, |type unions |, |characteristic predicates |, |member predicates |, |non-member predicates |
566+
567+ The ``overlay[local?] `` annotation declares that a predicate should be local if all of
568+ its dependencies are local, and global otherwise. This is particularly useful in
569+ parameterized modules, where different instantiations may have different locality
570+ depending on the module parameters.
571+
572+ .. code-block :: ql
573+
574+ // Locality depends on whether Expr.getType() and Type.getName() are local
575+ overlay[local?]
576+ predicate exprTypeName(Expr e, string name) {
577+ name = e.getType().getName()
578+ }
579+
580+ ``overlay[global] ``
581+ -------------------
582+
583+ **Available for **: |modules |, |classes |, |algebraic datatypes |, |type unions |, |characteristic predicates |, |member predicates |, |non-member predicates |
584+
585+ The ``overlay[global] `` annotation explicitly declares that a predicate is global. This
586+ is the default behavior, so this annotation is typically used to override an inherited
587+ ``overlay[local] `` or ``overlay[local?] `` annotation from an enclosing module or class.
588+ See `Annotation inheritance `_ for an example.
589+
590+ ``overlay[caller] ``
591+ -------------------
592+
593+ **Available for **: |modules |, |classes |, |algebraic datatypes |, |type unions |, |characteristic predicates |, |member predicates |, |non-member predicates |
594+
595+ The ``overlay[caller] `` annotation declares that the locality of a predicate depends on
596+ its caller. The compiler may internally duplicate the predicate, creating separate local
597+ and global versions. Local callers use the local version; global callers use the global
598+ version.
599+
600+ .. code-block :: ql
601+
602+ overlay[caller]
603+ predicate utilityPredicate(int x) {
604+ x in [1..100]
605+ }
606+
607+ ``overlay[caller?] ``
608+ --------------------
609+
610+ **Available for **: |modules |, |classes |, |algebraic datatypes |, |type unions |, |characteristic predicates |, |member predicates |, |non-member predicates |
611+
612+ The ``overlay[caller?] `` annotation is like ``overlay[caller] ``, but only applies if none
613+ of the predicate's dependencies are global. If any dependency is global, the predicate
614+ becomes global regardless of its callers, and calling it from a local predicate will
615+ result in a compilation error. Like ``overlay[local?] ``, this is useful in parameterized
616+ modules where locality may vary between instantiations.
617+
618+ ``overlay[discard_entity] ``
619+ ---------------------------
620+
621+ **Available for **: |non-member predicates | (unary predicates on database types only)
622+
623+ The ``overlay[discard_entity] `` annotation designates an *entity discard predicate *.
624+ These predicates identify database entities that should be filtered out from cached base
625+ results when combining with overlay results during overlay evaluation.
626+
627+ Entity discard predicates must be:
628+
629+ - Unary predicates (taking exactly one argument)
630+ - Defined on a database type (a type from the database schema, prefixed with ``@ ``)
631+ - Only dependent on local predicates and other non-discarding predicates
632+
633+ .. code-block :: ql
634+
635+ overlay[discard_entity]
636+ private predicate discardExpr(@expr e) {
637+ exists(string file | discardableExpr(file, e) and overlayChangedFiles(file))
638+ }
639+
640+ overlay[local]
641+ private predicate discardableExpr(string file, @expr e) {
642+ not isOverlay() and
643+ file = getFile(e)
644+ }
645+
646+ overlay[local]
647+ predicate isOverlay() { databaseMetadata("isOverlay", "true") }
648+
649+ Annotation inheritance
650+ ----------------------
651+
652+ Overlay annotations can be applied to modules and types, in which case they are
653+ inherited by enclosed declarations. Declarations without explicit overlay annotations
654+ inherit from their innermost enclosing declaration that has an overlay annotation.
655+
656+ .. code-block :: ql
657+
658+ overlay[local?]
659+ module M {
660+ predicate foo(@expr x) { ... } // Inherits overlay[local?]
661+
662+ class C extends @expr {
663+ predicate bar() { ... } // Inherits overlay[local?]
664+
665+ overlay[global]
666+ predicate baz() { ... } // Explicitly global
667+ }
668+ }
669+
670+ Resolving overlay-related errors
671+ --------------------------------
672+
673+ When overlay support is enabled for a language, you may encounter compilation errors in
674+ custom QL libraries or queries. Here are common errors and their solutions:
675+
676+ **"Declaration is annotated overlay[local] but depends on global entity" **
677+
678+ A predicate marked ``overlay[local] `` (or ``overlay[caller] ``) depends on a global predicate.
679+ Solutions:
680+
681+ - Change the annotation to ``overlay[local?] `` (or ``overlay[caller?] ``) if the predicate doesn't strictly need to be local
682+ - Add appropriate overlay annotations to the dependency chain to make dependencies local
683+ - Use the ``forceLocal `` higher-order predicate if you need to call global code from local code (advanced)
684+
685+ **"Cannot apply forceLocal to relation that is annotated overlay[...]" **
686+
687+ The ``forceLocal `` higher-order predicate cannot be applied to predicates that have overlay
688+ annotations such as ``overlay[local] ``, ``overlay[local?] ``, ``overlay[caller] ``, or
689+ ``overlay[caller?] ``. The input to ``forceLocal `` must be a predicate without such annotations
690+ (i.e., a global predicate or one with ``overlay[global] ``).
691+
505692.. Links to use in substitutions
506693
507694 .. |classes | replace :: :ref: `classes <classes >`
0 commit comments