-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: Data flow through variants #18078
Conversation
02c27dd
to
966b0f4
Compare
966b0f4
to
7f52abf
Compare
58c6327
to
4ec9dce
Compare
4ec9dce
to
5e7cd46
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really great 🎉 . I've just left a few questions and suggestions.
or | ||
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _) | ||
or | ||
exists(AssignmentExprCfgNode a | | ||
a.getRhs() = nodeFrom.getCfgNode() and | ||
a.getLhs() = nodeTo.getCfgNode() | ||
) | ||
or | ||
exists(MatchExprCfgNode match | | ||
nodeFrom.asExpr() = match.getScrutinee() and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love how much more readable this got after @redsun82's PR.
} | ||
|
||
/** | ||
* A reference contained in an object. For example a field in a struct. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* A reference contained in an object. For example a field in a struct. | |
* A path to a value contained in an object. For example a field name of a struct. |
// TODO: Remove once library types are extracted | ||
crate.isNone() and | ||
path = "crate::std::option::Option" and | ||
name = "Some" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we'd get a lot of mileage out of also special casing Result
here.
abstract Content getAReadContent(); | ||
} | ||
|
||
private class SingletonContentSet extends ContentSet, TSingletonContentSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private class SingletonContentSet extends ContentSet, TSingletonContentSet { | |
final private class SingletonContentSet extends ContentSet, TSingletonContentSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not super important, as the class is not exposed, but ok.
hasExtendedCanonicalPath(result, crate, path) and | ||
resolvesExtendedCanonicalPath(call, crate, path) | ||
hasExtendedCanonicalPath(result.asCfgScope(), crate, path) and | ||
callResolveExtendedCanonicalPath(call.asCallBaseExprCfgNode().getExpr(), crate, path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If DataFlowCall
had this getResolvable
predicate then this line could be (could also be a private predicate if we don't want a member predicate on DataFlowCall
):
callResolveExtendedCanonicalPath(call.asCallBaseExprCfgNode().getExpr(), crate, path) | |
resolveExtendedCanonicalPath(call.getResolvable(), crate, path) |
And callResolveExtendedCanonicalPath
could be deleted. That seems simpler and factors out "get resolveable" from "call resolveExtendedCanonicalPath" which are currently together inresolveExtendedCanonicalPath
.
|
||
final class ContentApprox = Void; | ||
final class ContentApprox = Content; // todo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final class ContentApprox = Content; // todo | |
final class ContentApprox = Content; // TODO: Implement content approximation. |
node1.asPat() = | ||
any(TupleStructPatCfgNode pat, int pos | | ||
tupleVariantDestruction(pat.getPat(), c.(TupleVariantContent).getVariantCanonicalPath(pos)) and | ||
node2.asPat() = pat.getField(pos) | ||
| | ||
pat | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about using exists
instead (also below)? I find that easier to read.
node1.asPat() = | |
any(TupleStructPatCfgNode pat, int pos | | |
tupleVariantDestruction(pat.getPat(), c.(TupleVariantContent).getVariantCanonicalPath(pos)) and | |
node2.asPat() = pat.getField(pos) | |
| | |
pat | |
) | |
exists(TupleStructPatCfgNode pat, int pos | | |
node1.asPat() = pat and | |
tupleVariantDestruction(pat.getPat(), c.(TupleVariantContent).getVariantCanonicalPath(pos)) and | |
node2.asPat() = pat.getField(pos) | |
) |
|
||
private class DataFlowCallAlias = DataFlowCall; | ||
/** A tuple variant. */ | ||
private class TupleVariantContent extends VariantContent, TTupleVariantContent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about naming this TupleVariantPosContent
to emphasize that its content stored in a specific position in a specific variant. I initially thought it was only the latter. Similarly, RecordVariantContent
could be RecordVariantFieldContent
.
|
||
pragma[nomagic] | ||
private predicate variantHasExtendedCanonicalPath( | ||
Enum e, Variant v, CrateOriginOption crate, string path, string name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: I've noticed that in QL predicates sometimes take more parameters than I would think necessary. Like here where name
only depends on v
and nothing else. Is that for performance reasons or because it's just convenient to have one relation with all the things and then use it with _
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be both, here it is mainly for convenience.
This PR adds support for tracking data flow through construction and deconstruction of enum variants. For example, we can now identify flow in cases such as
Commit-by-commit review is suggested.