From a2b7fcca2286a2d1b27b473e67c33c03bdfeab18 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 4 Nov 2024 08:45:54 +0100 Subject: [PATCH] Rust: Auto-generate `CfgNodes.qll` --- misc/codegen/codegen.py | 3 + misc/codegen/generators/qlgen.py | 26 +- misc/codegen/lib/ql.py | 52 + misc/codegen/lib/schema.py | 1 + misc/codegen/lib/schemadefs.py | 3 +- misc/codegen/loaders/schemaloader.py | 4 + misc/codegen/templates/ql_cfg_nodes.mustache | 183 + rust/codegen.conf | 1 + rust/ql/.generated.list | 1 + rust/ql/.gitattributes | 1 + .../lib/codeql/rust/controlflow/CfgNodes.qll | 10 +- .../controlflow/internal/CfgConsistency.qll | 4 + .../rust/controlflow/internal/CfgNodes.qll | 69 + .../internal/generated/CfgNodes.qll | 3185 +++++++++++++++++ rust/schema/annotations.py | 98 +- 15 files changed, 3582 insertions(+), 59 deletions(-) create mode 100644 misc/codegen/templates/ql_cfg_nodes.mustache create mode 100644 rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll create mode 100644 rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll diff --git a/misc/codegen/codegen.py b/misc/codegen/codegen.py index acc8e59bba5f3..9b84010a9a5e0 100755 --- a/misc/codegen/codegen.py +++ b/misc/codegen/codegen.py @@ -64,6 +64,9 @@ def _parse_args() -> argparse.Namespace: help="registry file containing information about checked-in generated code. A .gitattributes" "file is generated besides it to mark those files with linguist-generated=true. Must" "be in a directory containing all generated code."), + p.add_argument("--ql-cfg-output", + help="output directory for QL CFG layer (optional)."), + ] p.add_argument("--script-name", help="script name to put in header comments of generated files. By default, the path of this " diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index c5e7153489b6b..321aa4f862b3a 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -117,6 +117,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic synth=bool(cls.synth) or prop.synth, type_is_hideable="ql_hideable" in lookup[prop.type].pragmas if prop.type in lookup else False, internal="ql_internal" in prop.pragmas, + # is_child=prop.is_child, ) if prop.is_single: args.update( @@ -160,6 +161,8 @@ def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> q prop = get_ql_property(cls, p, lookup, prev_child) if prop.is_child: prev_child = prop.singular + if lookup[prop.type].cfg: + prop.cfg = True properties.append(prop) return ql.Class( name=cls.name, @@ -171,6 +174,15 @@ def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> q doc=cls.doc, hideable="ql_hideable" in cls.pragmas, internal="ql_internal" in cls.pragmas, + cfg=cls.cfg, + ) + +def get_ql_cfg_class(cls: schema.Class, lookup: typing.Dict[str, ql.Class]) -> ql.CfgClass: + return ql.CfgClass( + name=cls.name, + bases=[base for base in cls.bases if lookup[base.base].cfg], + properties=cls.properties, + doc=cls.doc ) @@ -361,6 +373,7 @@ def generate(opts, renderer): input = opts.schema out = opts.ql_output stub_out = opts.ql_stub_output + cfg_out = opts.ql_cfg_output test_out = opts.ql_test_output missing_test_source_filename = "MISSING_SOURCE.txt" include_file = stub_out.with_suffix(".qll") @@ -385,6 +398,7 @@ def generate(opts, renderer): imports = {} imports_impl = {} classes_used_by = {} + cfg_classes = {} generated_import_prefix = get_import(out, opts.root_dir) registry = opts.generated_registry or pathlib.Path( os.path.commonpath((out, stub_out, test_out)), ".generated.list") @@ -402,7 +416,9 @@ def generate(opts, renderer): imports[c.name] = path path_impl = get_import(stub_out / c.dir / "internal" / c.name, opts.root_dir) imports_impl[c.name + "Impl"] = path_impl + "Impl" - + if c.cfg: + cfg_classes[c.name] = get_ql_cfg_class(c, classes) + for c in classes.values(): qll = out / c.path.with_suffix(".qll") c.imports = [imports[t] if t in imports else imports_impl[t] + @@ -411,6 +427,14 @@ def generate(opts, renderer): c.import_prefix = generated_import_prefix renderer.render(c, qll) + if cfg_out: + cfg_classes_val = ql.CfgClasses( + include_file_import = get_import(include_file, opts.root_dir), + classes=list(cfg_classes.values()) + ) + cfg_qll = cfg_out / "CfgNodes.qll" + renderer.render(cfg_classes_val, cfg_qll) + for c in data.classes.values(): path = _get_path(c) path_impl = _get_path_impl(c) diff --git a/misc/codegen/lib/ql.py b/misc/codegen/lib/ql.py index 1920a813e20d8..95fc1e1063765 100644 --- a/misc/codegen/lib/ql.py +++ b/misc/codegen/lib/ql.py @@ -45,6 +45,7 @@ class Property: synth: bool = False type_is_hideable: bool = False internal: bool = False + cfg: bool = False def __post_init__(self): if self.tableparams: @@ -110,6 +111,7 @@ class Class: internal: bool = False doc: List[str] = field(default_factory=list) hideable: bool = False + cfg: bool = False def __post_init__(self): def get_bases(bases): return [Base(str(b), str(prev)) for b, prev in zip(bases, itertools.chain([""], bases))] @@ -333,3 +335,53 @@ class ConstructorStub: cls: "Synth.FinalClass" import_prefix: str + +@dataclass +class CfgClass: + name: str + bases: List[Base] = field(default_factory=list) + # bases_impl: List[Base] = field(default_factory=list) + # final: bool = False + properties: List[Property] = field(default_factory=list) + # dir: pathlib.Path = pathlib.Path() + # imports: List[str] = field(default_factory=list) + # import_prefix: Optional[str] = None + # internal: bool = False + doc: List[str] = field(default_factory=list) + # hideable: bool = False + + def __post_init__(self): + def get_bases(bases): return [Base(str(b), str(prev)) for b, prev in zip(bases, itertools.chain([""], bases))] + self.bases = get_bases(self.bases) + # self.bases_impl = get_bases(self.bases_impl) + if self.properties: + self.properties[0].first = True + + @property + def root(self) -> bool: + return not self.bases + + # @property + # def path(self) -> pathlib.Path: + # return self.dir / self.name + + # @property + # def db_id(self) -> str: + # return "@" + inflection.underscore(self.name) + + # @property + # def has_children(self) -> bool: + # return any(p.is_child for p in self.properties) + + @property + def last_base(self) -> str: + return self.bases[-1].base if self.bases else "" + +@dataclass +class CfgClasses: + template: ClassVar = 'ql_cfg_nodes' + + include_file_import: Optional[str] = None + + classes: List[CfgClass] = field(default_factory=list) + diff --git a/misc/codegen/lib/schema.py b/misc/codegen/lib/schema.py index c5c3dc810b680..23f1aea2ba42e 100644 --- a/misc/codegen/lib/schema.py +++ b/misc/codegen/lib/schema.py @@ -94,6 +94,7 @@ class Class: properties: List[Property] = field(default_factory=list) pragmas: List[str] | Dict[str, object] = field(default_factory=dict) doc: List[str] = field(default_factory=list) + cfg: bool = False def __post_init__(self): if not isinstance(self.pragmas, dict): diff --git a/misc/codegen/lib/schemadefs.py b/misc/codegen/lib/schemadefs.py index 997b85b4ca6af..32d3a6b85aedb 100644 --- a/misc/codegen/lib/schemadefs.py +++ b/misc/codegen/lib/schemadefs.py @@ -279,7 +279,7 @@ def __or__(self, other: _schema.PropertyModifier): drop = object() -def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None) -> _Callable[[type], _PropertyAnnotation]: +def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyAnnotation]: """ Add or modify schema annotations after a class has been defined previously. @@ -298,6 +298,7 @@ def decorator(cls: type) -> _PropertyAnnotation: annotated_cls.__bases__ = tuple(replace_bases.get(b, b) for b in annotated_cls.__bases__) if add_bases: annotated_cls.__bases__ += tuple(add_bases) + annotated_cls.__cfg__ = cfg for a in dir(cls): if a.startswith(_schema.inheritable_pragma_prefix): setattr(annotated_cls, a, getattr(cls, a)) diff --git a/misc/codegen/loaders/schemaloader.py b/misc/codegen/loaders/schemaloader.py index 069e3b654740a..162354fe18634 100644 --- a/misc/codegen/loaders/schemaloader.py +++ b/misc/codegen/loaders/schemaloader.py @@ -49,10 +49,14 @@ def _get_class(cls: type) -> schema.Class: derived = {d.__name__ for d in cls.__subclasses__()} if "null" in pragmas and derived: raise schema.Error(f"Null class cannot be derived") + cfg = False + if hasattr(cls, "__cfg__"): + cfg = cls.__cfg__ return schema.Class(name=cls.__name__, bases=[b.__name__ for b in cls.__bases__ if b is not object], derived=derived, pragmas=pragmas, + cfg=cfg, # todo? # in the following we don't use `getattr` to avoid inheriting properties=[ a | _PropertyNamer(n) diff --git a/misc/codegen/templates/ql_cfg_nodes.mustache b/misc/codegen/templates/ql_cfg_nodes.mustache new file mode 100644 index 0000000000000..e1be0671f975d --- /dev/null +++ b/misc/codegen/templates/ql_cfg_nodes.mustache @@ -0,0 +1,183 @@ +// generated by {{generator}}, do not edit +/** + * This module provides generated wrappers around the `CfgNode` type. + * + * INTERNAL: Do not import directly. + */ + +private import codeql.util.Location +private import {{include_file_import}} + +/** Provides the input to `MakeCfgNodes` */ +signature module InputSig { + class CfgNode { + AstNode getAstNode(); + + string toString(); + + Loc getLocation(); + } + + AstNode getDesugared(AstNode n); +} + +/** + * Given a `CfgNode` implementation, provides the module `Nodes` that + * contains wrappers around `CfgNode` for relevant classes. + */ +module MakeCfgNodes Input> { + private import Input + + final private class AstNodeFinal = AstNode; + + final private class CfgNodeFinal = CfgNode; + + /** + * INTERNAL: Do not expose. + */ + abstract class ChildMapping extends AstNodeFinal { + /** + * Holds if `child` is a (possibly nested) child of this AST node + * for which we would like to find a matching CFG child. + */ + abstract predicate relevantChild(AstNode child); + + /** + * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn` + * is a control-flow node for this AST node, and `cfnChild` is a control-flow + * node for `child`. + * + * This predicate should be implemented at the place where `MakeCfgNodes` is + * invoked. + */ + cached + predicate hasCfgChild(AstNode child, CfgNode cfn, CfgNode cfnChild) { none() } + } + + /** Provides sub classes of `CfgNode`. */ + module Nodes { + {{#classes}} + private final class {{name}}ChildMapping extends ChildMapping, {{name}} { + override predicate relevantChild(AstNode child) { + none() + {{#properties}} + {{#cfg}} + or + child = this.{{getter}}({{#is_indexed}}_{{/is_indexed}}) + {{/cfg}} + {{/properties}} + } + } + + /** + {{#doc}} + * {{.}} + {{/doc}} + */ + final class {{name}}CfgNode extends CfgNodeFinal{{#bases}}, {{.}}CfgNode{{/bases}} { + private {{name}}ChildMapping node; + + {{name}}CfgNode() { + node = this.getAstNode() + } + + /** Gets the underlying `{{name}}`. */ + {{name}} get{{name}}() { result = node } + + {{#properties}} + /** + * {{>ql_property_doc}} * + {{#description}} + * {{.}} + {{/description}} + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + {{type}}{{#cfg}}CfgNode{{/cfg}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { + {{#cfg}} + node.hasCfgChild(node.{{getter}}({{#is_indexed}}index{{/is_indexed}}), this, result) + {{/cfg}} + {{^cfg}} + {{^is_predicate}}result = {{/is_predicate}}node.{{getter}}({{#is_indexed}}index{{/is_indexed}}) + {{/cfg}} + } + + {{#is_optional}} + /** + * Holds if `{{getter}}({{#is_repeated}}index{{/is_repeated}})` exists. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) { + exists(this.{{getter}}({{#is_repeated}}index{{/is_repeated}})) + } + {{/is_optional}} + {{#is_indexed}} + + /** + * Gets any of the {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + {{type}}{{#cfg}}CfgNode{{/cfg}} {{indefinite_getter}}() { + result = this.{{getter}}(_) + } + {{^is_optional}} + + /** + * Gets the number of {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + int getNumberOf{{plural}}() { + result = count(int i | exists(this.{{getter}}(i))) + } + {{/is_optional}} + {{/is_indexed}} + {{#is_unordered}} + /** + * Gets the number of {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + int getNumberOf{{plural}}() { + result = count(this.{{getter}}()) + } + {{/is_unordered}} + {{/properties}} + } + {{/classes}} + } + + module Consistency { + private predicate hasCfgNode(AstNode astNode) { + astNode = any(CfgNode cfgNode).getAstNode() + } + + query predicate missingCfgChild(CfgNode parent, string pred, int child) { + none() + {{#classes}} + {{#properties}} + {{#cfg}} + or + pred = "{{getter}}" and + parent = any(Nodes::{{name}}CfgNode cfgNode, {{name}} astNode, {{type}} res | + astNode = cfgNode.get{{name}}() and + res = getDesugared(astNode.{{getter}}({{#is_indexed}}child{{/is_indexed}})) + {{^is_indexed}}and child = -1{{/is_indexed}} and + hasCfgNode(res) and + not res = cfgNode.{{getter}}({{#is_indexed}}child{{/is_indexed}}).getAstNode() + | + cfgNode + ) + {{/cfg}} + {{/properties}} + {{/classes}} + } + } +} \ No newline at end of file diff --git a/rust/codegen.conf b/rust/codegen.conf index 29b6edc89853f..d40fada446bbc 100644 --- a/rust/codegen.conf +++ b/rust/codegen.conf @@ -4,6 +4,7 @@ --dbscheme=ql/lib/rust.dbscheme --ql-output=ql/lib/codeql/rust/elements/internal/generated --ql-stub-output=ql/lib/codeql/rust/elements +--ql-cfg-output=ql/lib/codeql/rust/controlflow/internal/generated --ql-test-output=ql/test/extractor-tests/generated --rust-output=extractor/src/generated --script-name=codegen diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index c42ae033fc96e..5657a88ff353a 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -1,3 +1,4 @@ +lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 482b6cb3d678f3b98f41be737ce0c49105dcb921175e4c36608cf3286b2d3e10 58dbfd8fec69fea4c449aa70624cb61974f86642e0fb3f790c2c0e5947089359 lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893 lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71 lib/codeql/rust/elements/ArrayExpr.qll a3e6e122632f4011644ec31b37f88b32fe3f2b7e388e7e878a6883309937049f 12ccb5873d95c433da5606fd371d182ef2f71b78d0c53c2d6dec10fa45852bdc diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 2d19334cbc733..843cae20e50a5 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -1,5 +1,6 @@ /.generated.list linguist-generated /.gitattributes linguist-generated +/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll linguist-generated /lib/codeql/rust/elements/Abi.qll linguist-generated /lib/codeql/rust/elements/ArgList.qll linguist-generated /lib/codeql/rust/elements/ArrayExpr.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll index a637c98cfd10e..64f20a9081f03 100644 --- a/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll +++ b/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll @@ -5,6 +5,8 @@ private import rust private import ControlFlowGraph +private import internal.CfgNodes +import Nodes /** A CFG node that corresponds to an element in the AST. */ class AstCfgNode extends CfgNode { @@ -12,11 +14,3 @@ class AstCfgNode extends CfgNode { AstCfgNode() { node = this.getAstNode() } } - -/** A CFG node that corresponds to an expression in the AST. */ -class ExprCfgNode extends AstCfgNode { - override Expr node; - - /** Gets the underlying expression. */ - Expr getExpr() { result = node } -} diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll b/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll index 668533f1c3dd5..3b5e88ee79ca6 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll @@ -8,6 +8,7 @@ import Consistency private import codeql.rust.controlflow.ControlFlowGraph private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl private import codeql.rust.controlflow.internal.Completion +import codeql.rust.controlflow.internal.CfgNodes::Consistency private predicate nonPostOrderExpr(Expr e) { not e instanceof LetExpr and @@ -95,4 +96,7 @@ int getCfgInconsistencyCounts(string type) { or type = "Non-PostOrderTree Expr node" and result = count(Expr e | nonPostOrderExpr(e) | e) + or + type = "Missing CFG child" and + result = count(CfgNode parent, string pred, int child | missingCfgChild(parent, pred, child)) } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll new file mode 100644 index 0000000000000..c7e55b0abe5a5 --- /dev/null +++ b/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll @@ -0,0 +1,69 @@ +private import rust +private import codeql.rust.controlflow.internal.generated.CfgNodes +private import codeql.rust.controlflow.ControlFlowGraph +private import codeql.rust.controlflow.BasicBlocks +private import codeql.rust.controlflow.CfgNodes + +private module CfgNodesInput implements InputSig { + private import codeql.rust.controlflow.ControlFlowGraph as Cfg + + class CfgNode = AstCfgNode; + + private AstNode desugar(AstNode n) { + result = n.(ParenPat).getPat() + or + result = n.(ParenExpr).getExpr() + } + + AstNode getDesugared(AstNode n) { + result = getDesugared(desugar(n)) + or + not exists(desugar(n)) and + result = n + } +} + +import MakeCfgNodes + +private class ChildMappingImpl extends ChildMapping { + ChildMappingImpl() { exists(this) } + + override predicate relevantChild(AstNode child) { this.(ChildMapping).relevantChild(child) } + + private predicate isPostOrder() { + this instanceof Expr and + not this instanceof LetExpr + or + this instanceof OrPat + or + this instanceof IdentPat + or + this instanceof LiteralPat + } + + pragma[nomagic] + predicate reachesBasicBlock(AstNode child, CfgNode cfn, BasicBlock bb) { + this.relevantChild(child) and + cfn.getAstNode() = this and + bb.getANode() = cfn + or + if this.isPostOrder() + then + exists(BasicBlock mid | + this.reachesBasicBlock(child, cfn, mid) and + bb = mid.getAPredecessor() and + not mid.getANode().getAstNode() = child + ) + else + exists(BasicBlock mid | + this.reachesBasicBlock(child, cfn, mid) and + bb = mid.getASuccessor() and + not mid.getANode().getAstNode() = child + ) + } + + override predicate hasCfgChild(AstNode child, AstCfgNode cfn, AstCfgNode cfnChild) { + this.reachesBasicBlock(child, cfn, cfnChild.getBasicBlock()) and + cfnChild.getAstNode() = CfgNodesInput::getDesugared(child) + } +} diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll new file mode 100644 index 0000000000000..d8c8c63d07ab7 --- /dev/null +++ b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll @@ -0,0 +1,3185 @@ +// generated by codegen, do not edit +/** + * This module provides generated wrappers around the `CfgNode` type. + * + * INTERNAL: Do not import directly. + */ + +private import codeql.util.Location +private import codeql.rust.elements + +/** Provides the input to `MakeCfgNodes` */ +signature module InputSig { + class CfgNode { + AstNode getAstNode(); + + string toString(); + + Loc getLocation(); + } + + AstNode getDesugared(AstNode n); +} + +/** + * Given a `CfgNode` implementation, provides the module `Nodes` that + * contains wrappers around `CfgNode` for relevant classes. + */ +module MakeCfgNodes Input> { + private import Input + + final private class AstNodeFinal = AstNode; + + final private class CfgNodeFinal = CfgNode; + + /** + * INTERNAL: Do not expose. + */ + abstract class ChildMapping extends AstNodeFinal { + /** + * Holds if `child` is a (possibly nested) child of this AST node + * for which we would like to find a matching CFG child. + */ + abstract predicate relevantChild(AstNode child); + + /** + * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn` + * is a control-flow node for this AST node, and `cfnChild` is a control-flow + * node for `child`. + * + * This predicate should be implemented at the place where `MakeCfgNodes` is + * invoked. + */ + cached + predicate hasCfgChild(AstNode child, CfgNode cfn, CfgNode cfnChild) { none() } + } + + /** Provides sub classes of `CfgNode`. */ + module Nodes { + final private class ArrayExprChildMapping extends ChildMapping, ArrayExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr(_) + } + } + + /** + * An array expression. For example: + * ```rust + * [1, 2, 3]; + * [1; 10]; + * ``` + */ + final class ArrayExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ArrayExprChildMapping node; + + ArrayExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ArrayExpr`. */ + ArrayExpr getArrayExpr() { result = node } + + /** + * Gets the `index`th attr of this array expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this array expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this array expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th expression of this array expression (0-based). + */ + ExprCfgNode getExpr(int index) { node.hasCfgChild(node.getExpr(index), this, result) } + + /** + * Gets any of the expressions of this array expression. + */ + ExprCfgNode getAnExpr() { result = this.getExpr(_) } + + /** + * Gets the number of expressions of this array expression. + */ + int getNumberOfExprs() { result = count(int i | exists(this.getExpr(i))) } + } + + final private class AsmExprChildMapping extends ChildMapping, AsmExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * An inline assembly expression. For example: + * ```rust + * unsafe { + * builtin # asm(_); + * } + * ``` + */ + final class AsmExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private AsmExprChildMapping node; + + AsmExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `AsmExpr`. */ + AsmExpr getAsmExpr() { result = node } + + /** + * Gets the `index`th attr of this asm expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this asm expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this asm expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this asm expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class AwaitExprChildMapping extends ChildMapping, AwaitExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * An `await` expression. For example: + * ```rust + * async { + * let x = foo().await; + * x + * } + * ``` + */ + final class AwaitExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private AwaitExprChildMapping node; + + AwaitExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `AwaitExpr`. */ + AwaitExpr getAwaitExpr() { result = node } + + /** + * Gets the `index`th attr of this await expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this await expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this await expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this await expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class BecomeExprChildMapping extends ChildMapping, BecomeExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `become` expression. For example: + * ```rust + * fn fact_a(n: i32, a: i32) -> i32 { + * if n == 0 { + * a + * } else { + * become fact_a(n - 1, n * a) + * } + * } + * ``` + */ + final class BecomeExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BecomeExprChildMapping node; + + BecomeExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BecomeExpr`. */ + BecomeExpr getBecomeExpr() { result = node } + + /** + * Gets the `index`th attr of this become expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this become expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this become expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this become expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class BinaryExprChildMapping extends ChildMapping, BinaryExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLhs() + or + child = this.getRhs() + } + } + + /** + * A binary operation expression. For example: + * ```rust + * x + y; + * x && y; + * x <= y; + * x = y; + * x += y; + * ``` + */ + final class BinaryExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BinaryExprChildMapping node; + + BinaryExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BinaryExpr`. */ + BinaryExpr getBinaryExpr() { result = node } + + /** + * Gets the `index`th attr of this binary expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this binary expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this binary expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the lhs of this binary expression, if it exists. + */ + ExprCfgNode getLhs() { node.hasCfgChild(node.getLhs(), this, result) } + + /** + * Holds if `getLhs()` exists. + */ + predicate hasLhs() { exists(this.getLhs()) } + + /** + * Gets the operator name of this binary expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the rhs of this binary expression, if it exists. + */ + ExprCfgNode getRhs() { node.hasCfgChild(node.getRhs(), this, result) } + + /** + * Holds if `getRhs()` exists. + */ + predicate hasRhs() { exists(this.getRhs()) } + } + + final private class BlockExprChildMapping extends ChildMapping, BlockExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A block expression. For example: + * ```rust + * { + * let x = 42; + * } + * ``` + * ```rust + * 'label: { + * let x = 42; + * x + * } + * ``` + */ + final class BlockExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BlockExprChildMapping node; + + BlockExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BlockExpr`. */ + BlockExpr getBlockExpr() { result = node } + + /** + * Gets the `index`th attr of this block expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this block expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this block expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Holds if this block expression is async. + */ + predicate isAsync() { node.isAsync() } + + /** + * Holds if this block expression is const. + */ + predicate isConst() { node.isConst() } + + /** + * Holds if this block expression is gen. + */ + predicate isGen() { node.isGen() } + + /** + * Holds if this block expression is move. + */ + predicate isMove() { node.isMove() } + + /** + * Holds if this block expression is try. + */ + predicate isTry() { node.isTry() } + + /** + * Holds if this block expression is unsafe. + */ + predicate isUnsafe() { node.isUnsafe() } + + /** + * Gets the label of this block expression, if it exists. + */ + Label getLabel() { result = node.getLabel() } + + /** + * Holds if `getLabel()` exists. + */ + predicate hasLabel() { exists(this.getLabel()) } + + /** + * Gets the statement list of this block expression, if it exists. + */ + StmtList getStmtList() { result = node.getStmtList() } + + /** + * Holds if `getStmtList()` exists. + */ + predicate hasStmtList() { exists(this.getStmtList()) } + } + + final private class BoxPatChildMapping extends ChildMapping, BoxPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A box pattern. For example: + * ```rust + * match x { + * box Option::Some(y) => y, + * box Option::None => 0, + * }; + * ``` + */ + final class BoxPatCfgNode extends CfgNodeFinal, PatCfgNode { + private BoxPatChildMapping node; + + BoxPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BoxPat`. */ + BoxPat getBoxPat() { result = node } + + /** + * Gets the pat of this box pat, if it exists. + */ + PatCfgNode getPat() { node.hasCfgChild(node.getPat(), this, result) } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class BreakExprChildMapping extends ChildMapping, BreakExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A break expression. For example: + * ```rust + * loop { + * if not_ready() { + * break; + * } + * } + * ``` + * ```rust + * let x = 'label: loop { + * if done() { + * break 'label 42; + * } + * }; + * ``` + * ```rust + * let x = 'label: { + * if exit() { + * break 'label 42; + * } + * 0; + * }; + * ``` + */ + final class BreakExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BreakExprChildMapping node; + + BreakExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BreakExpr`. */ + BreakExpr getBreakExpr() { result = node } + + /** + * Gets the `index`th attr of this break expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this break expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this break expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this break expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the lifetime of this break expression, if it exists. + */ + Lifetime getLifetime() { result = node.getLifetime() } + + /** + * Holds if `getLifetime()` exists. + */ + predicate hasLifetime() { exists(this.getLifetime()) } + } + + final private class CallExprChildMapping extends ChildMapping, CallExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A function call expression. For example: + * ```rust + * foo(42); + * foo::(42); + * foo[0](42); + * foo(1) = 4; + * ``` + */ + final class CallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode { + private CallExprChildMapping node; + + CallExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `CallExpr`. */ + CallExpr getCallExpr() { result = node } + + /** + * Gets the expression of this call expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class CallExprBaseChildMapping extends ChildMapping, CallExprBase { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details. + */ + final class CallExprBaseCfgNode extends CfgNodeFinal, ExprCfgNode { + private CallExprBaseChildMapping node; + + CallExprBaseCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `CallExprBase`. */ + CallExprBase getCallExprBase() { result = node } + + /** + * Gets the argument list of this call expression base, if it exists. + */ + ArgList getArgList() { result = node.getArgList() } + + /** + * Holds if `getArgList()` exists. + */ + predicate hasArgList() { exists(this.getArgList()) } + + /** + * Gets the `index`th attr of this call expression base (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this call expression base. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this call expression base. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ConstBlockPatChildMapping extends ChildMapping, ConstBlockPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getBlockExpr() + } + } + + /** + * A const block pattern. For example: + * ```rust + * match x { + * const { 1 + 2 + 3 } => "ok", + * _ => "fail", + * }; + * ``` + */ + final class ConstBlockPatCfgNode extends CfgNodeFinal, PatCfgNode { + private ConstBlockPatChildMapping node; + + ConstBlockPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ConstBlockPat`. */ + ConstBlockPat getConstBlockPat() { result = node } + + /** + * Gets the block expression of this const block pat, if it exists. + */ + BlockExprCfgNode getBlockExpr() { node.hasCfgChild(node.getBlockExpr(), this, result) } + + /** + * Holds if `getBlockExpr()` exists. + */ + predicate hasBlockExpr() { exists(this.getBlockExpr()) } + + /** + * Holds if this const block pat is const. + */ + predicate isConst() { node.isConst() } + } + + final private class ContinueExprChildMapping extends ChildMapping, ContinueExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A continue expression. For example: + * ```rust + * loop { + * if not_ready() { + * continue; + * } + * } + * ``` + * ```rust + * 'label: loop { + * if not_ready() { + * continue 'label; + * } + * } + * ``` + */ + final class ContinueExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ContinueExprChildMapping node; + + ContinueExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ContinueExpr`. */ + ContinueExpr getContinueExpr() { result = node } + + /** + * Gets the `index`th attr of this continue expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this continue expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this continue expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the lifetime of this continue expression, if it exists. + */ + Lifetime getLifetime() { result = node.getLifetime() } + + /** + * Holds if `getLifetime()` exists. + */ + predicate hasLifetime() { exists(this.getLifetime()) } + } + + final private class ExprChildMapping extends ChildMapping, Expr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * The base class for expressions. + */ + final class ExprCfgNode extends CfgNodeFinal { + private ExprChildMapping node; + + ExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `Expr`. */ + Expr getExpr() { result = node } + } + + final private class FieldExprChildMapping extends ChildMapping, FieldExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A field access expression. For example: + * ```rust + * x.foo + * ``` + */ + final class FieldExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private FieldExprChildMapping node; + + FieldExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FieldExpr`. */ + FieldExpr getFieldExpr() { result = node } + + /** + * Gets the `index`th attr of this field expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this field expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this field expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this field expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the name reference of this field expression, if it exists. + */ + NameRef getNameRef() { result = node.getNameRef() } + + /** + * Holds if `getNameRef()` exists. + */ + predicate hasNameRef() { exists(this.getNameRef()) } + } + + final private class ForExprChildMapping extends ChildMapping, ForExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getIterable() + or + child = this.getLoopBody() + or + child = this.getPat() + } + } + + /** + * A ForExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class ForExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ForExprChildMapping node; + + ForExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ForExpr`. */ + ForExpr getForExpr() { result = node } + + /** + * Gets the `index`th attr of this for expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this for expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this for expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the iterable of this for expression, if it exists. + */ + ExprCfgNode getIterable() { node.hasCfgChild(node.getIterable(), this, result) } + + /** + * Holds if `getIterable()` exists. + */ + predicate hasIterable() { exists(this.getIterable()) } + + /** + * Gets the label of this for expression, if it exists. + */ + Label getLabel() { result = node.getLabel() } + + /** + * Holds if `getLabel()` exists. + */ + predicate hasLabel() { exists(this.getLabel()) } + + /** + * Gets the loop body of this for expression, if it exists. + */ + BlockExprCfgNode getLoopBody() { node.hasCfgChild(node.getLoopBody(), this, result) } + + /** + * Holds if `getLoopBody()` exists. + */ + predicate hasLoopBody() { exists(this.getLoopBody()) } + + /** + * Gets the pat of this for expression, if it exists. + */ + PatCfgNode getPat() { node.hasCfgChild(node.getPat(), this, result) } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class FormatArgsExprChildMapping extends ChildMapping, FormatArgsExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getTemplate() + } + } + + /** + * A FormatArgsExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class FormatArgsExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private FormatArgsExprChildMapping node; + + FormatArgsExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FormatArgsExpr`. */ + FormatArgsExpr getFormatArgsExpr() { result = node } + + /** + * Gets the `index`th argument of this format arguments expression (0-based). + */ + FormatArgsArg getArg(int index) { result = node.getArg(index) } + + /** + * Gets any of the arguments of this format arguments expression. + */ + FormatArgsArg getAnArg() { result = this.getArg(_) } + + /** + * Gets the number of arguments of this format arguments expression. + */ + int getNumberOfArgs() { result = count(int i | exists(this.getArg(i))) } + + /** + * Gets the `index`th attr of this format arguments expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this format arguments expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this format arguments expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the template of this format arguments expression, if it exists. + */ + ExprCfgNode getTemplate() { node.hasCfgChild(node.getTemplate(), this, result) } + + /** + * Holds if `getTemplate()` exists. + */ + predicate hasTemplate() { exists(this.getTemplate()) } + } + + final private class FormatTemplateVariableAccessChildMapping extends ChildMapping, + FormatTemplateVariableAccess + { + override predicate relevantChild(AstNode child) { none() } + } + + /** + */ + final class FormatTemplateVariableAccessCfgNode extends CfgNodeFinal, PathExprBaseCfgNode { + private FormatTemplateVariableAccessChildMapping node; + + FormatTemplateVariableAccessCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FormatTemplateVariableAccess`. */ + FormatTemplateVariableAccess getFormatTemplateVariableAccess() { result = node } + } + + final private class IdentPatChildMapping extends ChildMapping, IdentPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A binding pattern. For example: + * ```rust + * match x { + * Option::Some(y) => y, + * Option::None => 0, + * }; + * ``` + * ```rust + * match x { + * y@Option::Some(_) => y, + * Option::None => 0, + * }; + * ``` + */ + final class IdentPatCfgNode extends CfgNodeFinal, PatCfgNode { + private IdentPatChildMapping node; + + IdentPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IdentPat`. */ + IdentPat getIdentPat() { result = node } + + /** + * Gets the `index`th attr of this ident pat (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this ident pat. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this ident pat. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Holds if this ident pat is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Holds if this ident pat is reference. + */ + predicate isRef() { node.isRef() } + + /** + * Gets the name of this ident pat, if it exists. + */ + Name getName() { result = node.getName() } + + /** + * Holds if `getName()` exists. + */ + predicate hasName() { exists(this.getName()) } + + /** + * Gets the pat of this ident pat, if it exists. + */ + PatCfgNode getPat() { node.hasCfgChild(node.getPat(), this, result) } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class IfExprChildMapping extends ChildMapping, IfExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getCondition() + or + child = this.getElse() + or + child = this.getThen() + } + } + + /** + * An `if` expression. For example: + * ```rust + * if x == 42 { + * println!("that's the answer"); + * } + * ``` + * ```rust + * let y = if x > 0 { + * 1 + * } else { + * 0 + * }; + * ``` + */ + final class IfExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private IfExprChildMapping node; + + IfExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IfExpr`. */ + IfExpr getIfExpr() { result = node } + + /** + * Gets the `index`th attr of this if expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this if expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this if expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the condition of this if expression, if it exists. + */ + ExprCfgNode getCondition() { node.hasCfgChild(node.getCondition(), this, result) } + + /** + * Holds if `getCondition()` exists. + */ + predicate hasCondition() { exists(this.getCondition()) } + + /** + * Gets the else of this if expression, if it exists. + */ + ExprCfgNode getElse() { node.hasCfgChild(node.getElse(), this, result) } + + /** + * Holds if `getElse()` exists. + */ + predicate hasElse() { exists(this.getElse()) } + + /** + * Gets the then of this if expression, if it exists. + */ + BlockExprCfgNode getThen() { node.hasCfgChild(node.getThen(), this, result) } + + /** + * Holds if `getThen()` exists. + */ + predicate hasThen() { exists(this.getThen()) } + } + + final private class IndexExprChildMapping extends ChildMapping, IndexExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getBase() + or + child = this.getIndex() + } + } + + /** + * An index expression. For example: + * ```rust + * list[42]; + * list[42] = 1; + * ``` + */ + final class IndexExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private IndexExprChildMapping node; + + IndexExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IndexExpr`. */ + IndexExpr getIndexExpr() { result = node } + + /** + * Gets the `index`th attr of this index expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this index expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this index expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the base of this index expression, if it exists. + */ + ExprCfgNode getBase() { node.hasCfgChild(node.getBase(), this, result) } + + /** + * Holds if `getBase()` exists. + */ + predicate hasBase() { exists(this.getBase()) } + + /** + * Gets the index of this index expression, if it exists. + */ + ExprCfgNode getIndex() { node.hasCfgChild(node.getIndex(), this, result) } + + /** + * Holds if `getIndex()` exists. + */ + predicate hasIndex() { exists(this.getIndex()) } + } + + final private class LetExprChildMapping extends ChildMapping, LetExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + or + child = this.getPat() + } + } + + /** + * A `let` expression. For example: + * ```rust + * if let Some(x) = maybe_some { + * println!("{}", x); + * } + * ``` + */ + final class LetExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LetExprChildMapping node; + + LetExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LetExpr`. */ + LetExpr getLetExpr() { result = node } + + /** + * Gets the `index`th attr of this let expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this let expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this let expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this let expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the pat of this let expression, if it exists. + */ + PatCfgNode getPat() { node.hasCfgChild(node.getPat(), this, result) } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class LiteralExprChildMapping extends ChildMapping, LiteralExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A literal expression. For example: + * ```rust + * 42; + * 42.0; + * "Hello, world!"; + * b"Hello, world!"; + * 'x'; + * b'x'; + * r"Hello, world!"; + * true; + * ``` + */ + final class LiteralExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LiteralExprChildMapping node; + + LiteralExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LiteralExpr`. */ + LiteralExpr getLiteralExpr() { result = node } + + /** + * Gets the `index`th attr of this literal expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this literal expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this literal expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the text value of this literal expression, if it exists. + */ + string getTextValue() { result = node.getTextValue() } + + /** + * Holds if `getTextValue()` exists. + */ + predicate hasTextValue() { exists(this.getTextValue()) } + } + + final private class LiteralPatChildMapping extends ChildMapping, LiteralPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLiteral() + } + } + + /** + * A literal pattern. For example: + * ```rust + * match x { + * 42 => "ok", + * _ => "fail", + * } + * ``` + */ + final class LiteralPatCfgNode extends CfgNodeFinal, PatCfgNode { + private LiteralPatChildMapping node; + + LiteralPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LiteralPat`. */ + LiteralPat getLiteralPat() { result = node } + + /** + * Gets the literal of this literal pat, if it exists. + */ + LiteralExprCfgNode getLiteral() { node.hasCfgChild(node.getLiteral(), this, result) } + + /** + * Holds if `getLiteral()` exists. + */ + predicate hasLiteral() { exists(this.getLiteral()) } + } + + final private class LoopExprChildMapping extends ChildMapping, LoopExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLoopBody() + } + } + + /** + * A loop expression. For example: + * ```rust + * loop { + * println!("Hello, world (again)!"); + * }; + * ``` + * ```rust + * 'label: loop { + * println!("Hello, world (once)!"); + * break 'label; + * }; + * ``` + * ```rust + * let mut x = 0; + * loop { + * if x < 10 { + * x += 1; + * } else { + * break; + * } + * }; + * ``` + */ + final class LoopExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LoopExprChildMapping node; + + LoopExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LoopExpr`. */ + LoopExpr getLoopExpr() { result = node } + + /** + * Gets the `index`th attr of this loop expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this loop expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this loop expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the label of this loop expression, if it exists. + */ + Label getLabel() { result = node.getLabel() } + + /** + * Holds if `getLabel()` exists. + */ + predicate hasLabel() { exists(this.getLabel()) } + + /** + * Gets the loop body of this loop expression, if it exists. + */ + BlockExprCfgNode getLoopBody() { node.hasCfgChild(node.getLoopBody(), this, result) } + + /** + * Holds if `getLoopBody()` exists. + */ + predicate hasLoopBody() { exists(this.getLoopBody()) } + } + + final private class MacroExprChildMapping extends ChildMapping, MacroExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A MacroExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class MacroExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private MacroExprChildMapping node; + + MacroExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroExpr`. */ + MacroExpr getMacroExpr() { result = node } + + /** + * Gets the macro call of this macro expression, if it exists. + */ + MacroCall getMacroCall() { result = node.getMacroCall() } + + /** + * Holds if `getMacroCall()` exists. + */ + predicate hasMacroCall() { exists(this.getMacroCall()) } + } + + final private class MacroPatChildMapping extends ChildMapping, MacroPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A MacroPat. For example: + * ```rust + * todo!() + * ``` + */ + final class MacroPatCfgNode extends CfgNodeFinal, PatCfgNode { + private MacroPatChildMapping node; + + MacroPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroPat`. */ + MacroPat getMacroPat() { result = node } + + /** + * Gets the macro call of this macro pat, if it exists. + */ + MacroCall getMacroCall() { result = node.getMacroCall() } + + /** + * Holds if `getMacroCall()` exists. + */ + predicate hasMacroCall() { exists(this.getMacroCall()) } + } + + final private class MethodCallExprChildMapping extends ChildMapping, MethodCallExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getReceiver() + } + } + + /** + * A method call expression. For example: + * ```rust + * x.foo(42); + * x.foo::(42); + * ``` + */ + final class MethodCallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode { + private MethodCallExprChildMapping node; + + MethodCallExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MethodCallExpr`. */ + MethodCallExpr getMethodCallExpr() { result = node } + + /** + * Gets the generic argument list of this method call expression, if it exists. + */ + GenericArgList getGenericArgList() { result = node.getGenericArgList() } + + /** + * Holds if `getGenericArgList()` exists. + */ + predicate hasGenericArgList() { exists(this.getGenericArgList()) } + + /** + * Gets the name reference of this method call expression, if it exists. + */ + NameRef getNameRef() { result = node.getNameRef() } + + /** + * Holds if `getNameRef()` exists. + */ + predicate hasNameRef() { exists(this.getNameRef()) } + + /** + * Gets the receiver of this method call expression, if it exists. + */ + ExprCfgNode getReceiver() { node.hasCfgChild(node.getReceiver(), this, result) } + + /** + * Holds if `getReceiver()` exists. + */ + predicate hasReceiver() { exists(this.getReceiver()) } + } + + final private class OffsetOfExprChildMapping extends ChildMapping, OffsetOfExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * An `offset_of` expression. For example: + * ```rust + * builtin # offset_of(Struct, field); + * ``` + */ + final class OffsetOfExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private OffsetOfExprChildMapping node; + + OffsetOfExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `OffsetOfExpr`. */ + OffsetOfExpr getOffsetOfExpr() { result = node } + + /** + * Gets the `index`th attr of this offset of expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this offset of expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this offset of expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th field of this offset of expression (0-based). + */ + NameRef getField(int index) { result = node.getField(index) } + + /** + * Gets any of the fields of this offset of expression. + */ + NameRef getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this offset of expression. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + + /** + * Gets the ty of this offset of expression, if it exists. + */ + TypeRef getTy() { result = node.getTy() } + + /** + * Holds if `getTy()` exists. + */ + predicate hasTy() { exists(this.getTy()) } + } + + final private class OrPatChildMapping extends ChildMapping, OrPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat(_) + } + } + + /** + * An or pattern. For example: + * ```rust + * match x { + * Option::Some(y) | Option::None => 0, + * } + * ``` + */ + final class OrPatCfgNode extends CfgNodeFinal, PatCfgNode { + private OrPatChildMapping node; + + OrPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `OrPat`. */ + OrPat getOrPat() { result = node } + + /** + * Gets the `index`th pat of this or pat (0-based). + */ + PatCfgNode getPat(int index) { node.hasCfgChild(node.getPat(index), this, result) } + + /** + * Gets any of the pats of this or pat. + */ + PatCfgNode getAPat() { result = this.getPat(_) } + + /** + * Gets the number of pats of this or pat. + */ + int getNumberOfPats() { result = count(int i | exists(this.getPat(i))) } + } + + final private class PatChildMapping extends ChildMapping, Pat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * The base class for patterns. + */ + final class PatCfgNode extends CfgNodeFinal { + private PatChildMapping node; + + PatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `Pat`. */ + Pat getPat() { result = node } + } + + final private class PathExprChildMapping extends ChildMapping, PathExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path expression. For example: + * ```rust + * let x = variable; + * let x = foo::bar; + * let y = ::foo; + * let z = ::foo; + * ``` + */ + final class PathExprCfgNode extends CfgNodeFinal, PathExprBaseCfgNode { + private PathExprChildMapping node; + + PathExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathExpr`. */ + PathExpr getPathExpr() { result = node } + + /** + * Gets the `index`th attr of this path expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this path expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this path expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the path of this path expression, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class PathExprBaseChildMapping extends ChildMapping, PathExprBase { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details. + */ + final class PathExprBaseCfgNode extends CfgNodeFinal, ExprCfgNode { + private PathExprBaseChildMapping node; + + PathExprBaseCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathExprBase`. */ + PathExprBase getPathExprBase() { result = node } + } + + final private class PathPatChildMapping extends ChildMapping, PathPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path pattern. For example: + * ```rust + * match x { + * Foo::Bar => "ok", + * _ => "fail", + * } + * ``` + */ + final class PathPatCfgNode extends CfgNodeFinal, PatCfgNode { + private PathPatChildMapping node; + + PathPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathPat`. */ + PathPat getPathPat() { result = node } + + /** + * Gets the path of this path pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class PrefixExprChildMapping extends ChildMapping, PrefixExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A unary operation expression. For example: + * ```rust + * let x = -42; + * let y = !true; + * let z = *ptr; + * ``` + */ + final class PrefixExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private PrefixExprChildMapping node; + + PrefixExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PrefixExpr`. */ + PrefixExpr getPrefixExpr() { result = node } + + /** + * Gets the `index`th attr of this prefix expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this prefix expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this prefix expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this prefix expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the operator name of this prefix expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + } + + final private class RangeExprChildMapping extends ChildMapping, RangeExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getEnd() + or + child = this.getStart() + } + } + + /** + * A range expression. For example: + * ```rust + * let x = 1..=10; + * let x = 1..10; + * let x = 10..; + * let x = ..10; + * let x = ..=10; + * let x = ..; + * ``` + */ + final class RangeExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RangeExprChildMapping node; + + RangeExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RangeExpr`. */ + RangeExpr getRangeExpr() { result = node } + + /** + * Gets the `index`th attr of this range expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this range expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this range expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the end of this range expression, if it exists. + */ + ExprCfgNode getEnd() { node.hasCfgChild(node.getEnd(), this, result) } + + /** + * Holds if `getEnd()` exists. + */ + predicate hasEnd() { exists(this.getEnd()) } + + /** + * Gets the operator name of this range expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the start of this range expression, if it exists. + */ + ExprCfgNode getStart() { node.hasCfgChild(node.getStart(), this, result) } + + /** + * Holds if `getStart()` exists. + */ + predicate hasStart() { exists(this.getStart()) } + } + + final private class RangePatChildMapping extends ChildMapping, RangePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getEnd() + or + child = this.getStart() + } + } + + /** + * A range pattern. For example: + * ```rust + * match x { + * ..15 => "too cold", + * 16..=25 => "just right", + * 26.. => "too hot", + * } + * ``` + */ + final class RangePatCfgNode extends CfgNodeFinal, PatCfgNode { + private RangePatChildMapping node; + + RangePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RangePat`. */ + RangePat getRangePat() { result = node } + + /** + * Gets the end of this range pat, if it exists. + */ + PatCfgNode getEnd() { node.hasCfgChild(node.getEnd(), this, result) } + + /** + * Holds if `getEnd()` exists. + */ + predicate hasEnd() { exists(this.getEnd()) } + + /** + * Gets the operator name of this range pat, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the start of this range pat, if it exists. + */ + PatCfgNode getStart() { node.hasCfgChild(node.getStart(), this, result) } + + /** + * Holds if `getStart()` exists. + */ + predicate hasStart() { exists(this.getStart()) } + } + + final private class RecordExprChildMapping extends ChildMapping, RecordExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A record expression. For example: + * ```rust + * let first = Foo { a: 1, b: 2 }; + * let second = Foo { a: 2, ..first }; + * Foo { a: 1, b: 2 }[2] = 10; + * Foo { .. } = second; + * ``` + */ + final class RecordExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RecordExprChildMapping node; + + RecordExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RecordExpr`. */ + RecordExpr getRecordExpr() { result = node } + + /** + * Gets the path of this record expression, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + + /** + * Gets the record expression field list of this record expression, if it exists. + */ + RecordExprFieldList getRecordExprFieldList() { result = node.getRecordExprFieldList() } + + /** + * Holds if `getRecordExprFieldList()` exists. + */ + predicate hasRecordExprFieldList() { exists(this.getRecordExprFieldList()) } + } + + final private class RecordPatChildMapping extends ChildMapping, RecordPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A record pattern. For example: + * ```rust + * match x { + * Foo { a: 1, b: 2 } => "ok", + * Foo { .. } => "fail", + * } + * ``` + */ + final class RecordPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RecordPatChildMapping node; + + RecordPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RecordPat`. */ + RecordPat getRecordPat() { result = node } + + /** + * Gets the path of this record pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + + /** + * Gets the record pat field list of this record pat, if it exists. + */ + RecordPatFieldList getRecordPatFieldList() { result = node.getRecordPatFieldList() } + + /** + * Holds if `getRecordPatFieldList()` exists. + */ + predicate hasRecordPatFieldList() { exists(this.getRecordPatFieldList()) } + } + + final private class RefExprChildMapping extends ChildMapping, RefExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A reference expression. For example: + * ```rust + * let ref_const = &foo; + * let ref_mut = &mut foo; + * let raw_const: &mut i32 = &raw const foo; + * let raw_mut: &mut i32 = &raw mut foo; + * ``` + */ + final class RefExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RefExprChildMapping node; + + RefExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RefExpr`. */ + RefExpr getRefExpr() { result = node } + + /** + * Gets the `index`th attr of this reference expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this reference expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this reference expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this reference expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Holds if this reference expression is const. + */ + predicate isConst() { node.isConst() } + + /** + * Holds if this reference expression is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Holds if this reference expression is raw. + */ + predicate isRaw() { node.isRaw() } + } + + final private class RefPatChildMapping extends ChildMapping, RefPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A reference pattern. For example: + * ```rust + * match x { + * &mut Option::Some(y) => y, + * &Option::None => 0, + * }; + * ``` + */ + final class RefPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RefPatChildMapping node; + + RefPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RefPat`. */ + RefPat getRefPat() { result = node } + + /** + * Holds if this reference pat is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Gets the pat of this reference pat, if it exists. + */ + PatCfgNode getPat() { node.hasCfgChild(node.getPat(), this, result) } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class RestPatChildMapping extends ChildMapping, RestPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A RestPat. For example: + * ```rust + * todo!() + * ``` + */ + final class RestPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RestPatChildMapping node; + + RestPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RestPat`. */ + RestPat getRestPat() { result = node } + + /** + * Gets the `index`th attr of this rest pat (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this rest pat. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this rest pat. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ReturnExprChildMapping extends ChildMapping, ReturnExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A return expression. For example: + * ```rust + * fn some_value() -> i32 { + * return 42; + * } + * ``` + * ```rust + * fn no_value() -> () { + * return; + * } + * ``` + */ + final class ReturnExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ReturnExprChildMapping node; + + ReturnExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ReturnExpr`. */ + ReturnExpr getReturnExpr() { result = node } + + /** + * Gets the `index`th attr of this return expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this return expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this return expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this return expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class SlicePatChildMapping extends ChildMapping, SlicePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat(_) + } + } + + /** + * A slice pattern. For example: + * ```rust + * match x { + * [1, 2, 3, 4, 5] => "ok", + * [1, 2, ..] => "fail", + * [x, y, .., z, 7] => "fail", + * } + * ``` + */ + final class SlicePatCfgNode extends CfgNodeFinal, PatCfgNode { + private SlicePatChildMapping node; + + SlicePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `SlicePat`. */ + SlicePat getSlicePat() { result = node } + + /** + * Gets the `index`th pat of this slice pat (0-based). + */ + PatCfgNode getPat(int index) { node.hasCfgChild(node.getPat(index), this, result) } + + /** + * Gets any of the pats of this slice pat. + */ + PatCfgNode getAPat() { result = this.getPat(_) } + + /** + * Gets the number of pats of this slice pat. + */ + int getNumberOfPats() { result = count(int i | exists(this.getPat(i))) } + } + + final private class TryExprChildMapping extends ChildMapping, TryExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A TryExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class TryExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private TryExprChildMapping node; + + TryExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TryExpr`. */ + TryExpr getTryExpr() { result = node } + + /** + * Gets the `index`th attr of this try expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this try expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this try expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this try expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class TupleExprChildMapping extends ChildMapping, TupleExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple expression. For example: + * ```rust + * (1, "one"); + * (2, "two")[0] = 3; + * ``` + */ + final class TupleExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private TupleExprChildMapping node; + + TupleExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TupleExpr`. */ + TupleExpr getTupleExpr() { result = node } + + /** + * Gets the `index`th attr of this tuple expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this tuple expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this tuple expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th field of this tuple expression (0-based). + */ + ExprCfgNode getField(int index) { node.hasCfgChild(node.getField(index), this, result) } + + /** + * Gets any of the fields of this tuple expression. + */ + ExprCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple expression. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + } + + final private class TuplePatChildMapping extends ChildMapping, TuplePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple pattern. For example: + * ```rust + * let (x, y) = (1, 2); + * let (a, b, .., z) = (1, 2, 3, 4, 5); + * ``` + */ + final class TuplePatCfgNode extends CfgNodeFinal, PatCfgNode { + private TuplePatChildMapping node; + + TuplePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TuplePat`. */ + TuplePat getTuplePat() { result = node } + + /** + * Gets the `index`th field of this tuple pat (0-based). + */ + PatCfgNode getField(int index) { node.hasCfgChild(node.getField(index), this, result) } + + /** + * Gets any of the fields of this tuple pat. + */ + PatCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple pat. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + } + + final private class TupleStructPatChildMapping extends ChildMapping, TupleStructPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple struct pattern. For example: + * ```rust + * match x { + * Tuple("a", 1, 2, 3) => "great", + * Tuple(.., 3) => "fine", + * Tuple(..) => "fail", + * }; + * ``` + */ + final class TupleStructPatCfgNode extends CfgNodeFinal, PatCfgNode { + private TupleStructPatChildMapping node; + + TupleStructPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TupleStructPat`. */ + TupleStructPat getTupleStructPat() { result = node } + + /** + * Gets the `index`th field of this tuple struct pat (0-based). + */ + PatCfgNode getField(int index) { node.hasCfgChild(node.getField(index), this, result) } + + /** + * Gets any of the fields of this tuple struct pat. + */ + PatCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple struct pat. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + + /** + * Gets the path of this tuple struct pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class UnderscoreExprChildMapping extends ChildMapping, UnderscoreExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * An underscore expression. For example: + * ```rust + * _ = 42; + * ``` + */ + final class UnderscoreExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private UnderscoreExprChildMapping node; + + UnderscoreExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `UnderscoreExpr`. */ + UnderscoreExpr getUnderscoreExpr() { result = node } + + /** + * Gets the `index`th attr of this underscore expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this underscore expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this underscore expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class WhileExprChildMapping extends ChildMapping, WhileExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getCondition() + or + child = this.getLoopBody() + } + } + + /** + * A WhileExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class WhileExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private WhileExprChildMapping node; + + WhileExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `WhileExpr`. */ + WhileExpr getWhileExpr() { result = node } + + /** + * Gets the `index`th attr of this while expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this while expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this while expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the condition of this while expression, if it exists. + */ + ExprCfgNode getCondition() { node.hasCfgChild(node.getCondition(), this, result) } + + /** + * Holds if `getCondition()` exists. + */ + predicate hasCondition() { exists(this.getCondition()) } + + /** + * Gets the label of this while expression, if it exists. + */ + Label getLabel() { result = node.getLabel() } + + /** + * Holds if `getLabel()` exists. + */ + predicate hasLabel() { exists(this.getLabel()) } + + /** + * Gets the loop body of this while expression, if it exists. + */ + BlockExprCfgNode getLoopBody() { node.hasCfgChild(node.getLoopBody(), this, result) } + + /** + * Holds if `getLoopBody()` exists. + */ + predicate hasLoopBody() { exists(this.getLoopBody()) } + } + + final private class WildcardPatChildMapping extends ChildMapping, WildcardPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A wildcard pattern. For example: + * ```rust + * let _ = 42; + * ``` + */ + final class WildcardPatCfgNode extends CfgNodeFinal, PatCfgNode { + private WildcardPatChildMapping node; + + WildcardPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `WildcardPat`. */ + WildcardPat getWildcardPat() { result = node } + } + + final private class YeetExprChildMapping extends ChildMapping, YeetExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `yeet` expression. For example: + * ```rust + * if x < size { + * do yeet "index out of bounds"; + * } + * ``` + */ + final class YeetExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private YeetExprChildMapping node; + + YeetExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `YeetExpr`. */ + YeetExpr getYeetExpr() { result = node } + + /** + * Gets the `index`th attr of this yeet expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this yeet expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this yeet expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this yeet expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class YieldExprChildMapping extends ChildMapping, YieldExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `yield` expression. For example: + * ```rust + * let one = #[coroutine] + * || { + * yield 1; + * }; + * ``` + */ + final class YieldExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private YieldExprChildMapping node; + + YieldExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `YieldExpr`. */ + YieldExpr getYieldExpr() { result = node } + + /** + * Gets the `index`th attr of this yield expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this yield expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this yield expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this yield expression, if it exists. + */ + ExprCfgNode getExpr() { node.hasCfgChild(node.getExpr(), this, result) } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + } + + module Consistency { + private predicate hasCfgNode(AstNode astNode) { astNode = any(CfgNode cfgNode).getAstNode() } + + query predicate missingCfgChild(CfgNode parent, string pred, int child) { + none() + or + pred = "getExpr" and + parent = + any(Nodes::ArrayExprCfgNode cfgNode, ArrayExpr astNode, Expr res | + astNode = cfgNode.getArrayExpr() and + res = getDesugared(astNode.getExpr(child)) and + hasCfgNode(res) and + not res = cfgNode.getExpr(child).getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::AsmExprCfgNode cfgNode, AsmExpr astNode, Expr res | + astNode = cfgNode.getAsmExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::AwaitExprCfgNode cfgNode, AwaitExpr astNode, Expr res | + astNode = cfgNode.getAwaitExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::BecomeExprCfgNode cfgNode, BecomeExpr astNode, Expr res | + astNode = cfgNode.getBecomeExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getLhs" and + parent = + any(Nodes::BinaryExprCfgNode cfgNode, BinaryExpr astNode, Expr res | + astNode = cfgNode.getBinaryExpr() and + res = getDesugared(astNode.getLhs()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getLhs().getAstNode() + | + cfgNode + ) + or + pred = "getRhs" and + parent = + any(Nodes::BinaryExprCfgNode cfgNode, BinaryExpr astNode, Expr res | + astNode = cfgNode.getBinaryExpr() and + res = getDesugared(astNode.getRhs()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getRhs().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::BoxPatCfgNode cfgNode, BoxPat astNode, Pat res | + astNode = cfgNode.getBoxPat() and + res = getDesugared(astNode.getPat()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::BreakExprCfgNode cfgNode, BreakExpr astNode, Expr res | + astNode = cfgNode.getBreakExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::CallExprCfgNode cfgNode, CallExpr astNode, Expr res | + astNode = cfgNode.getCallExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getBlockExpr" and + parent = + any(Nodes::ConstBlockPatCfgNode cfgNode, ConstBlockPat astNode, BlockExpr res | + astNode = cfgNode.getConstBlockPat() and + res = getDesugared(astNode.getBlockExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getBlockExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::FieldExprCfgNode cfgNode, FieldExpr astNode, Expr res | + astNode = cfgNode.getFieldExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getIterable" and + parent = + any(Nodes::ForExprCfgNode cfgNode, ForExpr astNode, Expr res | + astNode = cfgNode.getForExpr() and + res = getDesugared(astNode.getIterable()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getIterable().getAstNode() + | + cfgNode + ) + or + pred = "getLoopBody" and + parent = + any(Nodes::ForExprCfgNode cfgNode, ForExpr astNode, BlockExpr res | + astNode = cfgNode.getForExpr() and + res = getDesugared(astNode.getLoopBody()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getLoopBody().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::ForExprCfgNode cfgNode, ForExpr astNode, Pat res | + astNode = cfgNode.getForExpr() and + res = getDesugared(astNode.getPat()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getTemplate" and + parent = + any(Nodes::FormatArgsExprCfgNode cfgNode, FormatArgsExpr astNode, Expr res | + astNode = cfgNode.getFormatArgsExpr() and + res = getDesugared(astNode.getTemplate()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getTemplate().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::IdentPatCfgNode cfgNode, IdentPat astNode, Pat res | + astNode = cfgNode.getIdentPat() and + res = getDesugared(astNode.getPat()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getCondition" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode, Expr res | + astNode = cfgNode.getIfExpr() and + res = getDesugared(astNode.getCondition()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getCondition().getAstNode() + | + cfgNode + ) + or + pred = "getElse" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode, Expr res | + astNode = cfgNode.getIfExpr() and + res = getDesugared(astNode.getElse()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getElse().getAstNode() + | + cfgNode + ) + or + pred = "getThen" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode, BlockExpr res | + astNode = cfgNode.getIfExpr() and + res = getDesugared(astNode.getThen()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getThen().getAstNode() + | + cfgNode + ) + or + pred = "getBase" and + parent = + any(Nodes::IndexExprCfgNode cfgNode, IndexExpr astNode, Expr res | + astNode = cfgNode.getIndexExpr() and + res = getDesugared(astNode.getBase()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getBase().getAstNode() + | + cfgNode + ) + or + pred = "getIndex" and + parent = + any(Nodes::IndexExprCfgNode cfgNode, IndexExpr astNode, Expr res | + astNode = cfgNode.getIndexExpr() and + res = getDesugared(astNode.getIndex()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getIndex().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::LetExprCfgNode cfgNode, LetExpr astNode, Expr res | + astNode = cfgNode.getLetExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::LetExprCfgNode cfgNode, LetExpr astNode, Pat res | + astNode = cfgNode.getLetExpr() and + res = getDesugared(astNode.getPat()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getLiteral" and + parent = + any(Nodes::LiteralPatCfgNode cfgNode, LiteralPat astNode, LiteralExpr res | + astNode = cfgNode.getLiteralPat() and + res = getDesugared(astNode.getLiteral()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getLiteral().getAstNode() + | + cfgNode + ) + or + pred = "getLoopBody" and + parent = + any(Nodes::LoopExprCfgNode cfgNode, LoopExpr astNode, BlockExpr res | + astNode = cfgNode.getLoopExpr() and + res = getDesugared(astNode.getLoopBody()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getLoopBody().getAstNode() + | + cfgNode + ) + or + pred = "getReceiver" and + parent = + any(Nodes::MethodCallExprCfgNode cfgNode, MethodCallExpr astNode, Expr res | + astNode = cfgNode.getMethodCallExpr() and + res = getDesugared(astNode.getReceiver()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getReceiver().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::OrPatCfgNode cfgNode, OrPat astNode, Pat res | + astNode = cfgNode.getOrPat() and + res = getDesugared(astNode.getPat(child)) and + hasCfgNode(res) and + not res = cfgNode.getPat(child).getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::PrefixExprCfgNode cfgNode, PrefixExpr astNode, Expr res | + astNode = cfgNode.getPrefixExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getEnd" and + parent = + any(Nodes::RangeExprCfgNode cfgNode, RangeExpr astNode, Expr res | + astNode = cfgNode.getRangeExpr() and + res = getDesugared(astNode.getEnd()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getEnd().getAstNode() + | + cfgNode + ) + or + pred = "getStart" and + parent = + any(Nodes::RangeExprCfgNode cfgNode, RangeExpr astNode, Expr res | + astNode = cfgNode.getRangeExpr() and + res = getDesugared(astNode.getStart()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getStart().getAstNode() + | + cfgNode + ) + or + pred = "getEnd" and + parent = + any(Nodes::RangePatCfgNode cfgNode, RangePat astNode, Pat res | + astNode = cfgNode.getRangePat() and + res = getDesugared(astNode.getEnd()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getEnd().getAstNode() + | + cfgNode + ) + or + pred = "getStart" and + parent = + any(Nodes::RangePatCfgNode cfgNode, RangePat astNode, Pat res | + astNode = cfgNode.getRangePat() and + res = getDesugared(astNode.getStart()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getStart().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::RefExprCfgNode cfgNode, RefExpr astNode, Expr res | + astNode = cfgNode.getRefExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::RefPatCfgNode cfgNode, RefPat astNode, Pat res | + astNode = cfgNode.getRefPat() and + res = getDesugared(astNode.getPat()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::ReturnExprCfgNode cfgNode, ReturnExpr astNode, Expr res | + astNode = cfgNode.getReturnExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::SlicePatCfgNode cfgNode, SlicePat astNode, Pat res | + astNode = cfgNode.getSlicePat() and + res = getDesugared(astNode.getPat(child)) and + hasCfgNode(res) and + not res = cfgNode.getPat(child).getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::TryExprCfgNode cfgNode, TryExpr astNode, Expr res | + astNode = cfgNode.getTryExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TupleExprCfgNode cfgNode, TupleExpr astNode, Expr res | + astNode = cfgNode.getTupleExpr() and + res = getDesugared(astNode.getField(child)) and + hasCfgNode(res) and + not res = cfgNode.getField(child).getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TuplePatCfgNode cfgNode, TuplePat astNode, Pat res | + astNode = cfgNode.getTuplePat() and + res = getDesugared(astNode.getField(child)) and + hasCfgNode(res) and + not res = cfgNode.getField(child).getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TupleStructPatCfgNode cfgNode, TupleStructPat astNode, Pat res | + astNode = cfgNode.getTupleStructPat() and + res = getDesugared(astNode.getField(child)) and + hasCfgNode(res) and + not res = cfgNode.getField(child).getAstNode() + | + cfgNode + ) + or + pred = "getCondition" and + parent = + any(Nodes::WhileExprCfgNode cfgNode, WhileExpr astNode, Expr res | + astNode = cfgNode.getWhileExpr() and + res = getDesugared(astNode.getCondition()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getCondition().getAstNode() + | + cfgNode + ) + or + pred = "getLoopBody" and + parent = + any(Nodes::WhileExprCfgNode cfgNode, WhileExpr astNode, BlockExpr res | + astNode = cfgNode.getWhileExpr() and + res = getDesugared(astNode.getLoopBody()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getLoopBody().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::YeetExprCfgNode cfgNode, YeetExpr astNode, Expr res | + astNode = cfgNode.getYeetExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::YieldExprCfgNode cfgNode, YieldExpr astNode, Expr res | + astNode = cfgNode.getYieldExpr() and + res = getDesugared(astNode.getExpr()) and + child = -1 and + hasCfgNode(res) and + not res = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + } + } +} diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index f8f5f182ad6f7..894ab911b01d9 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -18,14 +18,14 @@ class _: """ -@annotate(Expr) +@annotate(Expr, cfg = True) class _: """ The base class for expressions. """ -@annotate(Pat) +@annotate(Pat, cfg = True) class _: """ The base class for patterns. @@ -107,7 +107,7 @@ class PathExprBase(Expr): """ -@annotate(PathExpr, replace_bases={Expr: PathExprBase}) +@annotate(PathExpr, replace_bases={Expr: PathExprBase}, cfg = True) class _: """ A path expression. For example: @@ -120,7 +120,7 @@ class _: """ -@annotate(IfExpr) +@annotate(IfExpr, cfg = True) class _: """ An `if` expression. For example: @@ -139,7 +139,7 @@ class _: """ -@annotate(LetExpr) +@annotate(LetExpr, cfg = True) @rust.doc_test_signature("(maybe_some: Option) -> ()") class _: """ @@ -152,7 +152,7 @@ class _: """ -@annotate(BlockExpr) +@annotate(BlockExpr, cfg = True) class _: """ A block expression. For example: @@ -170,7 +170,7 @@ class _: """ -@annotate(LoopExpr) +@annotate(LoopExpr, cfg = True) class _: """ A loop expression. For example: @@ -206,7 +206,7 @@ class CallExprBase(Expr): attrs: list["Attr"] | child -@annotate(CallExpr, replace_bases={Expr: CallExprBase}) +@annotate(CallExpr, replace_bases={Expr: CallExprBase}, cfg = True) class _: """ A function call expression. For example: @@ -221,7 +221,7 @@ class _: attrs: drop -@annotate(MethodCallExpr, replace_bases={Expr: CallExprBase}) +@annotate(MethodCallExpr, replace_bases={Expr: CallExprBase}, cfg = True) class _: """ A method call expression. For example: @@ -274,7 +274,7 @@ class _: """ -@annotate(ContinueExpr) +@annotate(ContinueExpr, cfg = True) class _: """ A continue expression. For example: @@ -295,7 +295,7 @@ class _: """ -@annotate(BreakExpr) +@annotate(BreakExpr, cfg = True) class _: """ A break expression. For example: @@ -324,7 +324,7 @@ class _: """ -@annotate(ReturnExpr) +@annotate(ReturnExpr, cfg = True) @rust.doc_test_signature(None) class _: """ @@ -342,7 +342,7 @@ class _: """ -@annotate(BecomeExpr) +@annotate(BecomeExpr, cfg = True) @rust.doc_test_signature(None) class _: """ @@ -359,7 +359,7 @@ class _: """ -@annotate(YieldExpr) +@annotate(YieldExpr, cfg = True) class _: """ A `yield` expression. For example: @@ -372,7 +372,7 @@ class _: """ -@annotate(YeetExpr) +@annotate(YeetExpr, cfg = True) class _: """ A `yeet` expression. For example: @@ -394,7 +394,7 @@ class _: """ -@annotate(RecordExpr) +@annotate(RecordExpr, cfg = True) class _: """ A record expression. For example: @@ -407,7 +407,7 @@ class _: """ -@annotate(FieldExpr) +@annotate(FieldExpr, cfg = True) class _: """ A field access expression. For example: @@ -417,7 +417,7 @@ class _: """ -@annotate(AwaitExpr) +@annotate(AwaitExpr, cfg = True) class _: """ An `await` expression. For example: @@ -440,7 +440,7 @@ class _: """ -@annotate(RefExpr) +@annotate(RefExpr, cfg = True) class _: """ A reference expression. For example: @@ -453,7 +453,7 @@ class _: """ -@annotate(PrefixExpr) +@annotate(PrefixExpr, cfg = True) class _: """ A unary operation expression. For example: @@ -465,7 +465,7 @@ class _: """ -@annotate(BinaryExpr) +@annotate(BinaryExpr, cfg = True) class _: """ A binary operation expression. For example: @@ -479,7 +479,7 @@ class _: """ -@annotate(RangeExpr) +@annotate(RangeExpr, cfg = True) class _: """ A range expression. For example: @@ -494,7 +494,7 @@ class _: """ -@annotate(IndexExpr) +@annotate(IndexExpr, cfg = True) class _: """ An index expression. For example: @@ -521,7 +521,7 @@ class _: """ -@annotate(TupleExpr) +@annotate(TupleExpr, cfg = True) class _: """ A tuple expression. For example: @@ -532,7 +532,7 @@ class _: """ -@annotate(ArrayExpr) +@annotate(ArrayExpr, cfg = True) class _: """ An array expression. For example: @@ -543,7 +543,7 @@ class _: """ -@annotate(LiteralExpr) +@annotate(LiteralExpr, cfg = True) class _: """ A literal expression. For example: @@ -560,7 +560,7 @@ class _: """ -@annotate(UnderscoreExpr) +@annotate(UnderscoreExpr, cfg = True) class _: """ An underscore expression. For example: @@ -570,7 +570,7 @@ class _: """ -@annotate(OffsetOfExpr) +@annotate(OffsetOfExpr, cfg = True) class _: """ An `offset_of` expression. For example: @@ -580,7 +580,7 @@ class _: """ -@annotate(AsmExpr) +@annotate(AsmExpr, cfg = True) class _: """ An inline assembly expression. For example: @@ -621,7 +621,7 @@ class _: """ -@annotate(WildcardPat) +@annotate(WildcardPat, cfg = True) class _: """ A wildcard pattern. For example: @@ -631,7 +631,7 @@ class _: """ -@annotate(TuplePat) +@annotate(TuplePat, cfg = True) class _: """ A tuple pattern. For example: @@ -642,7 +642,7 @@ class _: """ -@annotate(OrPat) +@annotate(OrPat, cfg = True) class _: """ An or pattern. For example: @@ -664,7 +664,7 @@ class _: """ -@annotate(RecordPat) +@annotate(RecordPat, cfg = True) class _: """ A record pattern. For example: @@ -677,7 +677,7 @@ class _: """ -@annotate(RangePat) +@annotate(RangePat, cfg = True) class _: """ A range pattern. For example: @@ -691,7 +691,7 @@ class _: """ -@annotate(SlicePat) +@annotate(SlicePat, cfg = True) class _: """ A slice pattern. For example: @@ -705,7 +705,7 @@ class _: """ -@annotate(PathPat) +@annotate(PathPat, cfg = True) class _: """ A path pattern. For example: @@ -718,7 +718,7 @@ class _: """ -@annotate(LiteralPat) +@annotate(LiteralPat, cfg = True) class _: """ A literal pattern. For example: @@ -731,7 +731,7 @@ class _: """ -@annotate(IdentPat) +@annotate(IdentPat, cfg = True) class _: """ A binding pattern. For example: @@ -750,7 +750,7 @@ class _: """ -@annotate(TupleStructPat) +@annotate(TupleStructPat, cfg = True) class _: """ A tuple struct pattern. For example: @@ -764,7 +764,7 @@ class _: """ -@annotate(RefPat) +@annotate(RefPat, cfg = True) class _: """ A reference pattern. For example: @@ -777,7 +777,7 @@ class _: """ -@annotate(BoxPat) +@annotate(BoxPat, cfg = True) class _: """ A box pattern. For example: @@ -790,7 +790,7 @@ class _: """ -@annotate(ConstBlockPat) +@annotate(ConstBlockPat, cfg = True) class _: """ A const block pattern. For example: @@ -991,7 +991,7 @@ class _: """ -@annotate(ForExpr) +@annotate(ForExpr, cfg = True) class _: """ A ForExpr. For example: @@ -1021,7 +1021,7 @@ class _: """ -@annotate(FormatArgsExpr) +@annotate(FormatArgsExpr, cfg = True) class _: """ A FormatArgsExpr. For example: @@ -1172,7 +1172,7 @@ class _: """ -@annotate(MacroExpr) +@annotate(MacroExpr, cfg = True) class _: """ A MacroExpr. For example: @@ -1195,7 +1195,7 @@ class _: """ -@annotate(MacroPat) +@annotate(MacroPat, cfg = True) class _: """ A MacroPat. For example: @@ -1438,7 +1438,7 @@ class _: """ -@annotate(RestPat) +@annotate(RestPat, cfg = True) class _: """ A RestPat. For example: @@ -1565,7 +1565,7 @@ class _: """ -@annotate(TryExpr) +@annotate(TryExpr, cfg = True) class _: """ A TryExpr. For example: @@ -1745,7 +1745,7 @@ class _: """ -@annotate(WhileExpr) +@annotate(WhileExpr, cfg = True) class _: """ A WhileExpr. For example: