-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SILGen] Generate a trap for unexpected cases in all @objc enums #14724
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
[SILGen] Generate a trap for unexpected cases in all @objc enums #14724
Conversation
SILBasicBlock *defaultBB = nullptr; | ||
/// Create destination blocks for switching over the cases in an enum defined | ||
/// by \p rows. | ||
static void generateEnumCaseBlocks( |
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 factored this out from its duplication across the "ownership" and "non-ownership" versions of the pattern-match generation (*shakes fist at @gottesmm*), so it might be easier to review the whitespace-insensitive diff.
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.
Two things:
- Can you put the refactoring in a separate commit? That will make the diff even /easier/ to read than whitespace-insensitive diff.
- I purposely duplicated the code so I could easily visualize the difference in between the two.
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.
- Fair, will do.
- Please don't do this in the future. You saw below that there was already an inconsistency in code coverage.
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.
@jrose-apple on 2:
-
At the time, it was going to be temporary, but other things took priority. When you are trying to make a large transition in a code base (like putting ownership into SILGen), it is "cleaner" to duplicate old -> new/fix new/remove the old. I was just interrupted by the +0 work. Once +0 is done, this is next on my list to fix.
-
I disagree strongly with your characterization that this code duplication directly resulted in the code coverage inconsistency. What resulted in the code coverage inconsistency is a lack of enough test coverage of our emission of code coverage. If we had test coverage of such paths, then the error would have never happened. That is like blaming a night time driver for hitting a hole dug by road construction crews, when the road construction crews did not put up any signs with warnings.
NOTE I am taking your word for the error. I have not looked at it.
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.
That being said, I do not think arguing about blame/etc about the coverage is productive, so lets drop that for now? ; ).
SILLocation loc = PatternMatchStmt; | ||
loc.setDebugLoc(rows[0].Pattern); | ||
// SEMANTIC SIL TODO: Once we have the representation of a switch_enum that | ||
// can take a +0 value, this extra copy should be a borrow. | ||
SILValue srcValue = src.getFinalManagedValue().copy(SGF, loc).forward(SGF); | ||
// FIXME: Pass caseCounts in here as well, as it is in | ||
// emitEnumElementDispatch. | ||
SGF.B.createSwitchEnum(loc, srcValue, defaultBB, caseBBs); |
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.
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.
Switch and case statements are handled for coverage reporting purposes. This might be more up @shajrawi's alley.
// If we fail to match anything, we trap. This can happen with a switch | ||
// over an @objc enum, which may contain any value of its underlying type. | ||
// FIXME: Even if we can't say what the invalid value was, we should at | ||
// least mention that this was because of a non-exhaustive enum. |
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.
@jckarter, do you think it's okay to commit this part now and file a follow-up bug to provide a message? Or do you think that should go in at the same time?
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 it's OK to do it piecemeal.
@swift-ci Please test |
Looks good. Do you have any tests for trapping on |
Ooh, good call. I'll add one now. |
05a092f
to
963fbe5
Compare
@swift-ci Please test |
Build failed |
Build failed |
Simple code size test: @swift-ci Please test compiler performance |
@swift-ci Please test compiler performance |
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.
Can you move the refactoring into a separate commit/pr? Also a quick comment about a DenseMap.
SILBasicBlock *defaultBB = nullptr; | ||
/// Create destination blocks for switching over the cases in an enum defined | ||
/// by \p rows. | ||
static void generateEnumCaseBlocks( |
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.
Two things:
- Can you put the refactoring in a separate commit? That will make the diff even /easier/ to read than whitespace-insensitive diff.
- I purposely duplicated the code so I could easily visualize the difference in between the two.
lib/SILGen/SILGenPattern.cpp
Outdated
} else { | ||
specRow.Patterns.push_back(nullptr); | ||
} | ||
llvm::DenseMap<EnumElementDecl*, unsigned> caseToIndex; |
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.
Can you change this to be a SmallDenseMap? DenseMap seems really heavy weight here.
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.
This isn't a change from what was there before, but sure. (Makes sense, most enums are small.)
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.
Yes. You are correct.
963fbe5
to
c2cb9d1
Compare
Already passed full-testing previously, so just doing a smoke test now. @swift-ci Please smoke test |
Filed rdar://problem/37728359 to improve the error message and assigned it to myself. |
@swift-ci Please smoke test |
This code is shared between emitEnumElementDispatch and emitEnumElementDispatchWithOwnership. Eventually the former will go away, but for now there's no need to have both copies (which really are the same). No intended functionality change.
(both C enums and Swift enums declared @objc), because of the "feature" in C of treating a value not declared as a case as a valid value of an enum. No more undefined behavior here! This bit can go in separately from all the work on exhaustive/frozen enums, which is still being discussed and will come later. rdar://problem/20420436
Noticed by MichaelG while reviewing my changes in the previous commit. No intended functionality change.
c2cb9d1
to
49e71c9
Compare
@swift-ci Please smoke test |
(both C enums and Swift enums declared
@objc
), because of the "feature" in C of treating a value not declared as a case as a valid value of an enum. No more undefined behavior here!This bit can go in separately from all the work on exhaustive/frozen enums, which is still being discussed and will come later.
rdar://problem/20420436