@@ -2843,14 +2843,28 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2843
2843
2844
2844
// Inline constructor for subject.
2845
2845
auto subject = ([&]() -> ConsumableManagedValue {
2846
- // If we have a move only value, ensure plus one and convert it. Switches
2847
- // always consume move only values.
2846
+ // If we have a noImplicitCopy value, ensure plus one and convert
2847
+ // it. Switches always consume move only values.
2848
+ //
2849
+ // NOTE: We purposely do not do this for pure move only types since for them
2850
+ // we emit everything at +0 and then run the BorrowToDestructure transform
2851
+ // upon them. The reason that we do this is that internally to
2852
+ // SILGenPattern, we always attempt to move from +1 -> +0 meaning that even
2853
+ // if we start at +1, we will go back to +0 given enough patterns to go
2854
+ // through. It is simpler to just let SILGenPattern do what it already wants
2855
+ // to do, rather than fight it or try to resusitate the "fake owned borrow"
2856
+ // path that we still use for address only types (and that we want to delete
2857
+ // once we have opaque values).
2848
2858
if (subjectMV.getType ().isMoveOnly () && subjectMV.getType ().isObject ()) {
2849
2859
if (subjectMV.getType ().isMoveOnlyWrapped ()) {
2850
2860
subjectMV = B.createOwnedMoveOnlyWrapperToCopyableValue (
2851
2861
S, subjectMV.ensurePlusOne (*this , S));
2852
2862
} else {
2853
- subjectMV = B.createMoveValue (S, subjectMV.ensurePlusOne (*this , S));
2863
+ // If we have a pure move only type and it is owned, borrow it so that
2864
+ // BorrowToDestructure can handle it.
2865
+ if (subjectMV.getOwnershipKind () == OwnershipKind::Owned) {
2866
+ subjectMV = subjectMV.borrow (*this , S);
2867
+ }
2854
2868
}
2855
2869
}
2856
2870
0 commit comments