mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #18609 from hvitved/rust/dataflow-path-resolution
Rust: Use `PathResolution` module in data flow
This commit is contained in:
@@ -14,6 +14,7 @@ private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
private import codeql.rust.dataflow.FlowSummary
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import codeql.rust.elements.internal.PathResolution as PathResolution
|
||||
|
||||
/**
|
||||
* A return kind. A return kind describes how a value can be returned from a
|
||||
@@ -603,46 +604,124 @@ module LocalFlow {
|
||||
}
|
||||
}
|
||||
|
||||
private import codeql.util.Option
|
||||
/**
|
||||
* Provides temporary modeling of built-in variants, for which no source code
|
||||
* `Item`s are available.
|
||||
*
|
||||
* TODO: Remove once library code is extracted.
|
||||
*/
|
||||
private module VariantInLib {
|
||||
private import codeql.util.Option
|
||||
|
||||
private class CrateOrigin extends string {
|
||||
CrateOrigin() {
|
||||
this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()]
|
||||
private class CrateOrigin extends string {
|
||||
CrateOrigin() { this = any(Resolvable r).getResolvedCrateOrigin() }
|
||||
}
|
||||
|
||||
private class CrateOriginOption = Option<CrateOrigin>::Option;
|
||||
|
||||
private CrateOriginOption langCoreCrate() { result.asSome() = "lang:core" }
|
||||
|
||||
private newtype TVariantInLib =
|
||||
MkVariantInLib(CrateOriginOption crate, string path, string name) {
|
||||
crate = langCoreCrate() and
|
||||
(
|
||||
path = "crate::option::Option" and
|
||||
name = "Some"
|
||||
or
|
||||
path = "crate::result::Result" and
|
||||
name = ["Ok", "Err"]
|
||||
)
|
||||
}
|
||||
|
||||
/** An enum variant from library code, represented by the enum's canonical path and the variant's name. */
|
||||
class VariantInLib extends MkVariantInLib {
|
||||
CrateOriginOption crate;
|
||||
string path;
|
||||
string name;
|
||||
|
||||
VariantInLib() { this = MkVariantInLib(crate, path, name) }
|
||||
|
||||
int getAPosition() {
|
||||
this = MkVariantInLib(langCoreCrate(), "crate::option::Option", "Some") and
|
||||
result = 0
|
||||
or
|
||||
this = MkVariantInLib(langCoreCrate(), "crate::result::Result", ["Ok", "Err"]) and
|
||||
result = 0
|
||||
}
|
||||
|
||||
string getExtendedCanonicalPath() { result = path + "::" + name }
|
||||
|
||||
string toString() { result = name }
|
||||
}
|
||||
|
||||
/** A tuple variant from library code. */
|
||||
class VariantInLibTupleFieldContent extends VariantContent, TVariantInLibTupleFieldContent {
|
||||
private VariantInLib::VariantInLib v;
|
||||
private int pos_;
|
||||
|
||||
VariantInLibTupleFieldContent() { this = TVariantInLibTupleFieldContent(v, pos_) }
|
||||
|
||||
VariantInLib::VariantInLib getVariantInLib(int pos) { result = v and pos = pos_ }
|
||||
|
||||
string getExtendedCanonicalPath() { result = v.getExtendedCanonicalPath() }
|
||||
|
||||
int getPosition() { result = pos_ }
|
||||
|
||||
final override string toString() {
|
||||
// only print indices when the arity is > 1
|
||||
if exists(TVariantInLibTupleFieldContent(v, 1))
|
||||
then result = v.toString() + "(" + pos_ + ")"
|
||||
else result = v.toString()
|
||||
}
|
||||
|
||||
final override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) {
|
||||
path = r.getResolvedPath() and
|
||||
(
|
||||
crate.asSome() = r.getResolvedCrateOrigin()
|
||||
or
|
||||
crate.isNone() and
|
||||
not r.hasResolvedCrateOrigin()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if path `p` resolves to variant `v`. */
|
||||
private predicate pathResolveToVariantInLib(PathAstNode p, VariantInLib v) {
|
||||
exists(CrateOriginOption crate, string path, string name |
|
||||
resolveExtendedCanonicalPath(p, pragma[only_bind_into](crate), path + "::" + name) and
|
||||
v = MkVariantInLib(pragma[only_bind_into](crate), path, name)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `p` destructs an enum variant `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate tupleVariantCanonicalDestruction(TupleStructPat p, VariantInLib v) {
|
||||
pathResolveToVariantInLib(p, v)
|
||||
}
|
||||
|
||||
bindingset[pos]
|
||||
predicate tupleVariantCanonicalDestruction(
|
||||
TupleStructPat pat, VariantInLibTupleFieldContent c, int pos
|
||||
) {
|
||||
tupleVariantCanonicalDestruction(pat, c.getVariantInLib(pos))
|
||||
}
|
||||
|
||||
/** Holds if `ce` constructs an enum value of type `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate tupleVariantCanonicalConstruction(CallExpr ce, VariantInLib v) {
|
||||
pathResolveToVariantInLib(ce.getFunction().(PathExpr), v)
|
||||
}
|
||||
|
||||
bindingset[pos]
|
||||
predicate tupleVariantCanonicalConstruction(CallExpr ce, VariantInLibTupleFieldContent c, int pos) {
|
||||
tupleVariantCanonicalConstruction(ce, c.getVariantInLib(pos))
|
||||
}
|
||||
}
|
||||
|
||||
private class CrateOriginOption = Option<CrateOrigin>::Option;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasExtendedCanonicalPath(Item i, CrateOriginOption crate, string path) {
|
||||
path = i.getExtendedCanonicalPath() and
|
||||
(
|
||||
crate.asSome() = i.getCrateOrigin()
|
||||
or
|
||||
crate.isNone() and
|
||||
not i.hasCrateOrigin()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate variantHasExtendedCanonicalPath(
|
||||
Enum e, Variant v, CrateOriginOption crate, string path, string name
|
||||
) {
|
||||
hasExtendedCanonicalPath(e, crate, path) and
|
||||
v = e.getVariantList().getAVariant() and
|
||||
name = v.getName().getText()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) {
|
||||
path = r.getResolvedPath() and
|
||||
(
|
||||
crate.asSome() = r.getResolvedCrateOrigin()
|
||||
or
|
||||
crate.isNone() and
|
||||
not r.hasResolvedCrateOrigin()
|
||||
)
|
||||
}
|
||||
class VariantInLibTupleFieldContent = VariantInLib::VariantInLibTupleFieldContent;
|
||||
|
||||
/**
|
||||
* A path to a value contained in an object. For example a field name of a struct.
|
||||
@@ -650,24 +729,9 @@ private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption c
|
||||
abstract class Content extends TContent {
|
||||
/** Gets a textual representation of this content. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A canonical path pointing to an enum variant. */
|
||||
class VariantCanonicalPath extends MkVariantCanonicalPath {
|
||||
CrateOriginOption crate;
|
||||
string path;
|
||||
string name;
|
||||
|
||||
VariantCanonicalPath() { this = MkVariantCanonicalPath(crate, path, name) }
|
||||
|
||||
/** Gets the underlying variant. */
|
||||
Variant getVariant() { variantHasExtendedCanonicalPath(_, result, crate, path, name) }
|
||||
|
||||
string getExtendedCanonicalPath() { result = path + "::" + name }
|
||||
|
||||
string toString() { result = name }
|
||||
|
||||
Location getLocation() { result = this.getVariant().getLocation() }
|
||||
/** Gets the location of this content. */
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -676,67 +740,76 @@ class VariantCanonicalPath extends MkVariantCanonicalPath {
|
||||
*/
|
||||
abstract class VariantContent extends Content { }
|
||||
|
||||
private TupleField getVariantTupleField(Variant v, int i) {
|
||||
result = v.getFieldList().(TupleFieldList).getField(i)
|
||||
}
|
||||
|
||||
/** A tuple variant. */
|
||||
private class VariantPositionContent extends VariantContent, TVariantPositionContent {
|
||||
private VariantCanonicalPath v;
|
||||
private class VariantTupleFieldContent extends VariantContent, TVariantTupleFieldContent {
|
||||
private Variant v;
|
||||
private int pos_;
|
||||
|
||||
VariantPositionContent() { this = TVariantPositionContent(v, pos_) }
|
||||
VariantTupleFieldContent() { this = TVariantTupleFieldContent(v, pos_) }
|
||||
|
||||
VariantCanonicalPath getVariantCanonicalPath(int pos) { result = v and pos = pos_ }
|
||||
Variant getVariant(int pos) { result = v and pos = pos_ }
|
||||
|
||||
final override string toString() {
|
||||
// only print indices when the arity is > 1
|
||||
if exists(TVariantPositionContent(v, 1))
|
||||
then result = v.toString() + "(" + pos_ + ")"
|
||||
else result = v.toString()
|
||||
exists(string name |
|
||||
name = v.getName().getText() and
|
||||
// only print indices when the arity is > 1
|
||||
if exists(getVariantTupleField(v, 1)) then result = name + "(" + pos_ + ")" else result = name
|
||||
)
|
||||
}
|
||||
|
||||
final override Location getLocation() { result = getVariantTupleField(v, pos_).getLocation() }
|
||||
}
|
||||
|
||||
private RecordField getVariantRecordField(Variant v, string field) {
|
||||
result = v.getFieldList().(RecordFieldList).getAField() and
|
||||
field = result.getName().getText()
|
||||
}
|
||||
|
||||
/** A record variant. */
|
||||
private class VariantFieldContent extends VariantContent, TVariantFieldContent {
|
||||
private VariantCanonicalPath v;
|
||||
private class VariantRecordFieldContent extends VariantContent, TVariantRecordFieldContent {
|
||||
private Variant v;
|
||||
private string field_;
|
||||
|
||||
VariantFieldContent() { this = TVariantFieldContent(v, field_) }
|
||||
VariantRecordFieldContent() { this = TVariantRecordFieldContent(v, field_) }
|
||||
|
||||
VariantCanonicalPath getVariantCanonicalPath(string field) { result = v and field = field_ }
|
||||
Variant getVariant(string field) { result = v and field = field_ }
|
||||
|
||||
final override string toString() {
|
||||
// only print field when the arity is > 1
|
||||
if strictcount(string f | exists(TVariantFieldContent(v, f))) > 1
|
||||
then result = v.toString() + "{" + field_ + "}"
|
||||
else result = v.toString()
|
||||
exists(string name |
|
||||
name = v.getName().getText() and
|
||||
// only print field when the arity is > 1
|
||||
if strictcount(string f | exists(getVariantRecordField(v, f))) > 1
|
||||
then result = name + "{" + field_ + "}"
|
||||
else result = name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A canonical path pointing to a struct. */
|
||||
class StructCanonicalPath extends MkStructCanonicalPath {
|
||||
CrateOriginOption crate;
|
||||
string path;
|
||||
|
||||
StructCanonicalPath() { this = MkStructCanonicalPath(crate, path) }
|
||||
|
||||
/** Gets the underlying struct. */
|
||||
Struct getStruct() { hasExtendedCanonicalPath(result, crate, path) }
|
||||
|
||||
string getExtendedCanonicalPath() { result = path }
|
||||
|
||||
string toString() { result = this.getStruct().getName().getText() }
|
||||
|
||||
Location getLocation() { result = this.getStruct().getLocation() }
|
||||
final override Location getLocation() {
|
||||
result = getVariantRecordField(v, field_).getName().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Content stored in a field on a struct. */
|
||||
private class StructFieldContent extends Content, TStructFieldContent {
|
||||
private StructCanonicalPath s;
|
||||
private Struct s;
|
||||
private string field_;
|
||||
|
||||
StructFieldContent() { this = TStructFieldContent(s, field_) }
|
||||
|
||||
StructCanonicalPath getStructCanonicalPath(string field) { result = s and field = field_ }
|
||||
Struct getStruct(string field) { result = s and field = field_ }
|
||||
|
||||
override string toString() { result = s.toString() + "." + field_.toString() }
|
||||
override string toString() { result = s.getName().getText() + "." + field_.toString() }
|
||||
|
||||
override Location getLocation() {
|
||||
exists(Name f | f = s.getFieldList().(RecordFieldList).getAField().getName() |
|
||||
f.getText() = field_ and
|
||||
result = f.getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A captured variable. */
|
||||
@@ -749,11 +822,15 @@ private class CapturedVariableContent extends Content, TCapturedVariableContent
|
||||
Variable getVariable() { result = v }
|
||||
|
||||
override string toString() { result = "captured " + v }
|
||||
|
||||
override Location getLocation() { result = v.getLocation() }
|
||||
}
|
||||
|
||||
/** A value referred to by a reference. */
|
||||
final class ReferenceContent extends Content, TReferenceContent {
|
||||
override string toString() { result = "&ref" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -766,6 +843,8 @@ final class ReferenceContent extends Content, TReferenceContent {
|
||||
*/
|
||||
final class ElementContent extends Content, TElementContent {
|
||||
override string toString() { result = "element" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,6 +861,8 @@ final class TuplePositionContent extends Content, TTuplePositionContent {
|
||||
int getPosition() { result = pos }
|
||||
|
||||
override string toString() { result = "tuple." + pos.toString() }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/** Holds if `access` indexes a tuple at an index corresponding to `c`. */
|
||||
@@ -1011,39 +1092,22 @@ module RustDataFlow implements InputSig<Location> {
|
||||
node2.(Node::FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
/** Holds if path `p` resolves to struct `s`. */
|
||||
private predicate pathResolveToStructCanonicalPath(PathAstNode p, StructCanonicalPath s) {
|
||||
exists(CrateOriginOption crate, string path |
|
||||
resolveExtendedCanonicalPath(p, crate, path) and
|
||||
s = MkStructCanonicalPath(crate, path)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if path `p` resolves to variant `v`. */
|
||||
private predicate pathResolveToVariantCanonicalPath(PathAstNode p, VariantCanonicalPath v) {
|
||||
exists(CrateOriginOption crate, string path, string name |
|
||||
resolveExtendedCanonicalPath(p, pragma[only_bind_into](crate), path + "::" + name) and
|
||||
v = MkVariantCanonicalPath(pragma[only_bind_into](crate), path, name)
|
||||
)
|
||||
/** Gets the item that `p` resolves to, if any. */
|
||||
private PathResolution::ItemNode resolvePath(PathAstNode p) {
|
||||
result = PathResolution::resolvePath(p.getPath())
|
||||
}
|
||||
|
||||
/** Holds if `p` destructs an enum variant `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate tupleVariantDestruction(TupleStructPat p, VariantCanonicalPath v) {
|
||||
pathResolveToVariantCanonicalPath(p, v)
|
||||
}
|
||||
private predicate tupleVariantDestruction(TupleStructPat p, Variant v) { v = resolvePath(p) }
|
||||
|
||||
/** Holds if `p` destructs an enum variant `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate recordVariantDestruction(RecordPat p, VariantCanonicalPath v) {
|
||||
pathResolveToVariantCanonicalPath(p, v)
|
||||
}
|
||||
private predicate recordVariantDestruction(RecordPat p, Variant v) { v = resolvePath(p) }
|
||||
|
||||
/** Holds if `p` destructs a struct `s`. */
|
||||
pragma[nomagic]
|
||||
private predicate structDestruction(RecordPat p, StructCanonicalPath s) {
|
||||
pathResolveToStructCanonicalPath(p, s)
|
||||
}
|
||||
private predicate structDestruction(RecordPat p, Struct s) { s = resolvePath(p) }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
|
||||
@@ -1054,9 +1118,11 @@ module RustDataFlow implements InputSig<Location> {
|
||||
exists(Content c | c = cs.(SingletonContentSet).getContent() |
|
||||
exists(TupleStructPatCfgNode pat, int pos |
|
||||
pat = node1.asPat() and
|
||||
tupleVariantDestruction(pat.getPat(),
|
||||
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
|
||||
node2.asPat() = pat.getField(pos)
|
||||
|
|
||||
tupleVariantDestruction(pat.getPat(), c.(VariantTupleFieldContent).getVariant(pos))
|
||||
or
|
||||
VariantInLib::tupleVariantCanonicalDestruction(pat.getPat(), c, pos)
|
||||
)
|
||||
or
|
||||
exists(TuplePatCfgNode pat, int pos |
|
||||
@@ -1069,11 +1135,10 @@ module RustDataFlow implements InputSig<Location> {
|
||||
pat = node1.asPat() and
|
||||
(
|
||||
// Pattern destructs a struct-like variant.
|
||||
recordVariantDestruction(pat.getPat(),
|
||||
c.(VariantFieldContent).getVariantCanonicalPath(field))
|
||||
recordVariantDestruction(pat.getPat(), c.(VariantRecordFieldContent).getVariant(field))
|
||||
or
|
||||
// Pattern destructs a struct.
|
||||
structDestruction(pat.getPat(), c.(StructFieldContent).getStructCanonicalPath(field))
|
||||
structDestruction(pat.getPat(), c.(StructFieldContent).getStruct(field))
|
||||
) and
|
||||
node2.asPat() = pat.getFieldPat(field)
|
||||
)
|
||||
@@ -1110,7 +1175,7 @@ module RustDataFlow implements InputSig<Location> {
|
||||
exists(TryExprCfgNode try |
|
||||
node1.asExpr() = try.getExpr() and
|
||||
node2.asExpr() = try and
|
||||
c.(VariantPositionContent).getVariantCanonicalPath(0).getExtendedCanonicalPath() =
|
||||
c.(VariantInLibTupleFieldContent).getVariantInLib(0).getExtendedCanonicalPath() =
|
||||
["crate::option::Option::Some", "crate::result::Result::Ok"]
|
||||
)
|
||||
or
|
||||
@@ -1130,21 +1195,17 @@ module RustDataFlow implements InputSig<Location> {
|
||||
|
||||
/** Holds if `ce` constructs an enum value of type `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate tupleVariantConstruction(CallExpr ce, VariantCanonicalPath v) {
|
||||
pathResolveToVariantCanonicalPath(ce.getFunction().(PathExpr), v)
|
||||
private predicate tupleVariantConstruction(CallExpr ce, Variant v) {
|
||||
v = resolvePath(ce.getFunction().(PathExpr))
|
||||
}
|
||||
|
||||
/** Holds if `re` constructs an enum value of type `v`. */
|
||||
pragma[nomagic]
|
||||
private predicate recordVariantConstruction(RecordExpr re, VariantCanonicalPath v) {
|
||||
pathResolveToVariantCanonicalPath(re, v)
|
||||
}
|
||||
private predicate recordVariantConstruction(RecordExpr re, Variant v) { v = resolvePath(re) }
|
||||
|
||||
/** Holds if `re` constructs a struct value of type `s`. */
|
||||
pragma[nomagic]
|
||||
private predicate structConstruction(RecordExpr re, StructCanonicalPath s) {
|
||||
pathResolveToStructCanonicalPath(re, s)
|
||||
}
|
||||
private predicate structConstruction(RecordExpr re, Struct s) { s = resolvePath(re) }
|
||||
|
||||
private predicate tupleAssignment(Node node1, Node node2, TuplePositionContent c) {
|
||||
exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access |
|
||||
@@ -1158,20 +1219,22 @@ module RustDataFlow implements InputSig<Location> {
|
||||
pragma[nomagic]
|
||||
private predicate storeContentStep(Node node1, Content c, Node node2) {
|
||||
exists(CallExprCfgNode call, int pos |
|
||||
tupleVariantConstruction(call.getCallExpr(),
|
||||
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
|
||||
node1.asExpr() = call.getArgument(pos) and
|
||||
node2.asExpr() = call
|
||||
|
|
||||
tupleVariantConstruction(call.getCallExpr(), c.(VariantTupleFieldContent).getVariant(pos))
|
||||
or
|
||||
VariantInLib::tupleVariantCanonicalConstruction(call.getCallExpr(), c, pos)
|
||||
)
|
||||
or
|
||||
exists(RecordExprCfgNode re, string field |
|
||||
(
|
||||
// Expression is for a struct-like enum variant.
|
||||
recordVariantConstruction(re.getRecordExpr(),
|
||||
c.(VariantFieldContent).getVariantCanonicalPath(field))
|
||||
c.(VariantRecordFieldContent).getVariant(field))
|
||||
or
|
||||
// Expression is for a struct.
|
||||
structConstruction(re.getRecordExpr(), c.(StructFieldContent).getStructCanonicalPath(field))
|
||||
structConstruction(re.getRecordExpr(), c.(StructFieldContent).getStruct(field))
|
||||
) and
|
||||
node1.asExpr() = re.getFieldExpr(field) and
|
||||
node2.asExpr() = re
|
||||
@@ -1529,46 +1592,12 @@ private module Cached {
|
||||
cached
|
||||
newtype TReturnKind = TNormalReturnKind()
|
||||
|
||||
private CrateOriginOption langCoreCrate() { result.asSome() = "lang:core" }
|
||||
|
||||
cached
|
||||
newtype TVariantCanonicalPath =
|
||||
MkVariantCanonicalPath(CrateOriginOption crate, string path, string name) {
|
||||
variantHasExtendedCanonicalPath(_, _, crate, path, name)
|
||||
or
|
||||
// TODO: Remove once library types are extracted
|
||||
crate = langCoreCrate() and
|
||||
(
|
||||
path = "crate::option::Option" and
|
||||
name = "Some"
|
||||
or
|
||||
path = "crate::result::Result" and
|
||||
name = ["Ok", "Err"]
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TStructCanonicalPath =
|
||||
MkStructCanonicalPath(CrateOriginOption crate, string path) {
|
||||
exists(Struct s | hasExtendedCanonicalPath(s, crate, path))
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TContent =
|
||||
TVariantPositionContent(VariantCanonicalPath v, int pos) {
|
||||
pos in [0 .. v.getVariant().getFieldList().(TupleFieldList).getNumberOfFields() - 1]
|
||||
or
|
||||
// TODO: Remove once library types are extracted
|
||||
v = MkVariantCanonicalPath(langCoreCrate(), "crate::option::Option", "Some") and
|
||||
pos = 0
|
||||
or
|
||||
// TODO: Remove once library types are extracted
|
||||
v = MkVariantCanonicalPath(langCoreCrate(), "crate::result::Result", ["Ok", "Err"]) and
|
||||
pos = 0
|
||||
} or
|
||||
TVariantFieldContent(VariantCanonicalPath v, string field) {
|
||||
field = v.getVariant().getFieldList().(RecordFieldList).getAField().getName().getText()
|
||||
} or
|
||||
TVariantTupleFieldContent(Variant v, int pos) { exists(getVariantTupleField(v, pos)) } or
|
||||
// TODO: Remove once library types are extracted
|
||||
TVariantInLibTupleFieldContent(VariantInLib::VariantInLib v, int pos) { pos = v.getAPosition() } or
|
||||
TVariantRecordFieldContent(Variant v, string field) { exists(getVariantRecordField(v, field)) } or
|
||||
TElementContent() or
|
||||
TTuplePositionContent(int pos) {
|
||||
pos in [0 .. max([
|
||||
@@ -1577,8 +1606,8 @@ private module Cached {
|
||||
]
|
||||
)]
|
||||
} or
|
||||
TStructFieldContent(StructCanonicalPath s, string field) {
|
||||
field = s.getStruct().getFieldList().(RecordFieldList).getAField().getName().getText()
|
||||
TStructFieldContent(Struct s, string field) {
|
||||
field = s.getFieldList().(RecordFieldList).getAField().getName().getText()
|
||||
} or
|
||||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
|
||||
TReferenceContent()
|
||||
|
||||
@@ -61,21 +61,30 @@ module Input implements InputSig<Location, RustDataFlow> {
|
||||
|
||||
string encodeContent(ContentSet cs, string arg) {
|
||||
exists(Content c | cs = TSingletonContentSet(c) |
|
||||
exists(VariantCanonicalPath v | result = "Variant" |
|
||||
exists(Variant v | result = "Variant" |
|
||||
exists(int pos |
|
||||
c = TVariantPositionContent(v, pos) and
|
||||
c = TVariantTupleFieldContent(v, pos) and
|
||||
// TODO: calculate in QL
|
||||
arg = v.getExtendedCanonicalPath() + "(" + pos + ")"
|
||||
)
|
||||
or
|
||||
exists(string field |
|
||||
c = TVariantFieldContent(v, field) and
|
||||
// TODO: calculate in QL
|
||||
c = TVariantRecordFieldContent(v, field) and
|
||||
arg = v.getExtendedCanonicalPath() + "::" + field
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(StructCanonicalPath s, string field |
|
||||
result = "Variant" and
|
||||
c =
|
||||
any(VariantInLibTupleFieldContent v |
|
||||
arg = v.getExtendedCanonicalPath() + "(" + v.getPosition() + ")"
|
||||
)
|
||||
or
|
||||
exists(Struct s, string field |
|
||||
result = "Struct" and
|
||||
c = TStructFieldContent(s, field) and
|
||||
// TODO: calculate in QL
|
||||
arg = s.getExtendedCanonicalPath() + "::" + field
|
||||
)
|
||||
or
|
||||
|
||||
Reference in New Issue
Block a user