Rust: Data flow through tuple and struct fields#18131
Conversation
4e4e27d to
d89678f
Compare
hvitved
left a comment
There was a problem hiding this comment.
LGTM, some minor things.
| } | ||
|
|
||
| /** Content stored in a field on a struct. */ | ||
| private class StructFieldContent extends VariantContent, TStructFieldContent { |
There was a problem hiding this comment.
I think this should extend Content instead of VariantContent.
| * NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal, | ||
| * hence we don't store a canonical path for them. | ||
| */ | ||
| private class TuplePositionContent extends VariantContent, TTuplePositionContent { |
| pathResolveToVariantCanonicalPath(p.getPath(), v) | ||
| } | ||
|
|
||
| /** Holds if `p` destructs an struct `s`. */ |
| pathResolveToVariantCanonicalPath(re.getPath(), v) | ||
| } | ||
|
|
||
| /** Holds if `re` constructs a struct value of type `v`. */ |
| exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access | | ||
| assignment.getLhs() = access and | ||
| n.asExpr() = access.getExpr() and | ||
| access.getNameRef().getText().toInt() = | ||
| c.(SingletonContentSet).getContent().(TuplePositionContent).getPosition() | ||
| ) |
There was a problem hiding this comment.
This part should also give rise to a store step (but where the toNode is the post-update node of n). That should remove the false negative inside tuple_mutation.
| exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access | | ||
| assignment.getLhs() = access and | ||
| fieldTuplePositionContent(access, c) and | ||
| node1.asExpr() = assignment.getRhs() and | ||
| node2.asExpr() = access.getExpr() | ||
| ) |
There was a problem hiding this comment.
Should be node2.(PostUpdateNode).getPreUpdateNode().asExpr(). But I think we should make a helper predicate
private predicate tupleAssignment(Node node1, Node node2, TuplePositionContent c) {
exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access |
assignment.getLhs() = access and
fieldTuplePositionContent(access, c) and
node1.asExpr() = assignment.getRhs() and
node2.asExpr() = access.getExpr()
)
}
Then the above becomes tupleAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c) and clearsContent becomes tupleAssignment(_, n, cs.(SingletonContentSet).getContent())
| /** Gets the node before the state update. */ | ||
| Node getPreUpdateNode() { result = TExprNode(n) } | ||
|
|
||
| override ExprCfgNode asExpr() { result = n } |
There was a problem hiding this comment.
We don't want this; this predicate should only hold for TExprNode.
There was a problem hiding this comment.
Yes, I realised that 😅
99c1c36 to
e1c65aa
Compare
|
I think the DCA looks fine. Alacritty went from 19564 data flow inconsistencies to 20356 but this is before #18144. |
Adds some amount of data flow through tuples and structs.
One notable omission is that field access to
structs is not handled. This is because the field in aFieldExpressionis aNameRefwhich is not a subclass ofResolvable. Hence we can not lookup whichstructthe field is actually for. I think we'll want to have the extractor resolve theseNameRefs as well, so we can do the same thing that we do for struct-like variants.