SILGen: Always match noncopyable values by borrowing. #71025
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.
Even if the final pattern ends up consuming the value, the match itself must be nondestructive, because any match condition could fail and cause us to have to go back to the original aggregate. For copyable values, we can always copy our way out of consuming operations, but we don't have that luxury for noncopyable types, so the entire match operation has to be done as a borrow.
For address-only enums, this requires codifying part of our tag layout algorithm in SIL, namely that an address-only enum will never use spare bits or other overlapping storage for the enum tag. This allows us to assume that
unchecked_take_enum_data_addr
is safely non-side- effecting and match an address-only noncopyable enum as a borrow. I put TODOs to remove defensive copies from various parts of our copyable enum codegen, as well as to have the instruction report its memory behavior asNone
when the projection is nondestructive, but this disturbs SILGen for existing code in ways SIL passes aren't yet ready for, so I'll leave those as is for now.This patch is enough to get simple examples of noncopyable enum switches to SILGen correctly. Additional work is necessary to stage in the binding step of the pattern match; for a consuming switch, we'll need to end the borrow(s) and then reproject the matched components so we can consume them moving them into the owned bindings. The move-only checker also needs to be updated because it currently always tries to convert a switch into a consuming operation.