Fix mutating method calls on class existentials #9573
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This builds upon #9625 and #9637 to address miscompiles and assertions with a peculiar corner case -- performing a mutating method call on a class existential.
This can manifest in one of two ways:
The root cause is that mutating methods take the opened
self
value as an inout parameter, but we had no way to model an inout access of the payload inside a class existential at the SIL level. I've decided to model it as a logical lvalue component where the "get" strips the existential witness tables to produce a reference, and the "set" adds the witness tables back to the reference to form a new existential.Note that this miscompile was occurring irrespective of whether the mutating method was defined in an extension, or in the class itself. The problem was that incorrect code was being generated at the call site, where it is not known how the method is implemented, and
self
has to be passed as an inout value.Fixes rdar://problem/31858378.