Skip to content

Swift: collection/tuple content for dictionary flow #13947

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

Merged
merged 14 commits into from
Sep 7, 2023

Conversation

rdmarsh2
Copy link
Contributor

This PR models dictionary content as being TupleContent nested within CollectionContent, and adds a new DictionarySubscriptNode to represent the intermediate step, where only the TupleContent has been stored, or only the CollectionContent has been read. This means models for the generic Collection protocol will work for dictionaries without modification.

@rdmarsh2 rdmarsh2 requested a review from a team as a code owner August 10, 2023 20:57
@github-actions github-actions bot added the Swift label Aug 10, 2023
@hvitved
Copy link
Contributor

hvitved commented Aug 11, 2023

This PR models dictionary content as being TupleContent nested within CollectionContent

FTR, this is also how it's done in C# 👍 (though instead of TupleContent it's a FieldContent representing a KeyValuePair)

@rdmarsh2
Copy link
Contributor Author

That's good to know. Swift has had first-class tuples from the start, so they just alias (Key, Value) as the element type.

Comment on lines 761 to 771
subscript.getArgument(0).getExpr() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
assign.getSource() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
node1.(DictionarySubscriptNode) = node1 and
node2.asExpr() = subscript and
c.isSingleton(any(Content::CollectionContent cc))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now we do:

source -> TupleContent -> CollectionContent

in two steps (which makes sense), and I gather that the last of these three cases is the CollectionContent step. But why do we need two cases to cover the first step? I would have thought that only the middle cases was needed, and the first case would happen through reverse reads?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are two steps to assemble the tuple because one is for the key and one is for the value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first case is the step from the key in dict[key] = value - I typoed and it should be tc.getIndex() = 0 there.

Comment on lines 761 to 771
subscript.getArgument(0).getExpr() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
assign.getSource() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
node1.(DictionarySubscriptNode) = node1 and
node2.asExpr() = subscript and
c.isSingleton(any(Content::CollectionContent cc))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are two steps to assemble the tuple because one is for the key and one is for the value.

Comment on lines 878 to 881
(
c.isSingleton(any(Content::FieldContent fc)) or
c.isSingleton(any(Content::TupleContent tc))
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this restriction? Do we not want to clear CollectionContent and ArrayContent?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... or EnumContent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to clear CollectionContent and ArrayContent at a post-update node because they may have been only partially overwritten - consider the case here. It shouldn't clear the content from line 779.

I think we do want to clear EnumContent, though. Good catch.

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concerns have been addressed, how about you @MathiasVP

@MathiasVP
Copy link
Contributor

My concerns have been addressed, how about you @MathiasVP

I think so, yes. I'd still like to see a DCA run on this PR, though 🙏. In addition, it would be nice if we could have a testcase that demonstrated the impact of 3ee3eab (although this can be done in a future PR if you prefer).

@geoffw0
Copy link
Contributor

geoffw0 commented Aug 22, 2023

Possible analysis performance regression showing in the DCA runs, particularly the second one. Not sure if it's real or wobble. A small real regression would be acceptable.

In addition, it would be nice if we could have a testcase that demonstrated the impact of 3ee3eab (although this can be done in a future PR if you prefer).

I agree.

@rdmarsh2
Copy link
Contributor Author

rdmarsh2 commented Sep 5, 2023

I haven't been able to find any obvious performance issues locally, and the worst cases do look like wobble (very high standard deviations for the slower run). I wonder if we should implement type pruning and see if that fixes performance...

@MathiasVP
Copy link
Contributor

If you can't reproduce it then it's probably fine. But let's do another DCA run after the merge-conflict has been resolved just to be safe 🤞.

@rdmarsh2
Copy link
Contributor Author

rdmarsh2 commented Sep 7, 2023

Timings in the latest DCA run look reasonable

@MathiasVP
Copy link
Contributor

MathiasVP commented Sep 7, 2023

Indeed, this LGTM! Now we just need to:

  • Do a round of autoformatting
  • Accept the test improvements

and then I think this PR is good to go 🎉

Copy link
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@MathiasVP MathiasVP merged commit 49fee35 into github:main Sep 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants