Skip to content

Commit 7d6f11d

Browse files
committed
[sema] Follow-up on the raw-representable casting fixits, produce a fixit for optional source types as well.
For optional source types we use the form "expr.map{ T(rawValue: $0) }".
1 parent 4f0d2a7 commit 7d6f11d

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3159,8 +3159,37 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
31593159
KnownProtocolKind kind,
31603160
Expr *expr) {
31613161
// The following fixes apply for optional destination types as well.
3162+
bool toTypeIsOptional = !toType->getAnyOptionalObjectType().isNull();
31623163
toType = toType->lookThroughAllAnyOptionalTypes();
31633164

3165+
Type fromTypeUnwrapped = fromType->getAnyOptionalObjectType();
3166+
bool fromTypeIsOptional = !fromTypeUnwrapped.isNull();
3167+
if (fromTypeIsOptional)
3168+
fromType = fromTypeUnwrapped;
3169+
3170+
auto fixIt = [&](StringRef convWrapBefore, StringRef convWrapAfter) {
3171+
SourceRange exprRange = expr->getSourceRange();
3172+
if (fromTypeIsOptional && toTypeIsOptional) {
3173+
// Use optional's map function to convert conditionally, like so:
3174+
// expr.map{ T(rawValue: $0) }
3175+
bool needsParens = !expr->canAppendCallParentheses();
3176+
std::string mapCodeFix;
3177+
if (needsParens) {
3178+
diag.fixItInsert(exprRange.Start, "(");
3179+
mapCodeFix += ")";
3180+
}
3181+
mapCodeFix += ".map{ ";
3182+
mapCodeFix += convWrapBefore;
3183+
mapCodeFix += "$0";
3184+
mapCodeFix += convWrapAfter;
3185+
mapCodeFix += " }";
3186+
diag.fixItInsertAfter(exprRange.End, mapCodeFix);
3187+
} else if (!fromTypeIsOptional) {
3188+
diag.fixItInsert(exprRange.Start, convWrapBefore);
3189+
diag.fixItInsertAfter(exprRange.End, convWrapAfter);
3190+
}
3191+
};
3192+
31643193
if (isLiteralConvertibleType(fromType, kind, CS)) {
31653194
if (auto rawTy = isRawRepresentable(toType, kind, CS)) {
31663195
// Produce before/after strings like 'Result(rawValue: RawType(<expr>))'
@@ -3173,9 +3202,7 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
31733202
convWrapBefore += "(";
31743203
convWrapAfter += ")";
31753204
}
3176-
SourceRange exprRange = expr->getSourceRange();
3177-
diag.fixItInsert(exprRange.Start, convWrapBefore);
3178-
diag.fixItInsertAfter(exprRange.End, convWrapAfter);
3205+
fixIt(convWrapBefore, convWrapAfter);
31793206
return;
31803207
}
31813208
}
@@ -3189,9 +3216,7 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
31893216
convWrapBefore += "(";
31903217
convWrapAfter += ")";
31913218
}
3192-
SourceRange exprRange = expr->getSourceRange();
3193-
diag.fixItInsert(exprRange.Start, convWrapBefore);
3194-
diag.fixItInsertAfter(exprRange.End, convWrapAfter);
3219+
fixIt(convWrapBefore, convWrapAfter);
31953220
return;
31963221
}
31973222
}

test/FixCode/fixits-apply.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ func testMask5(a: Int) {
5656
func testMask6(a: Int) {
5757
sendItOpt(a)
5858
}
59+
func testMask7(a: Int?) {
60+
sendItOpt(a)
61+
}
62+
func testMask8(a: UInt64?) {
63+
sendItOpt(a)
64+
}
65+
func testMask9(a: Any) {
66+
sendItOpt(a as? Int)
67+
}
68+
func testMask10(a: Int?) {
69+
sendIt(a) // no fix, nullability mismatch.
70+
}
71+
func testMask11(a: MyEventMask2?) {
72+
testMask7(a: a)
73+
}
74+
func testMask12(a: MyEventMask2?) {
75+
testMask8(a: a)
76+
}
77+
func testMask13(a: MyEventMask2?) {
78+
testMask1(a: a) // no fix, nullability mismatch.
79+
}
5980

6081
enum MyEnumType : UInt32 {
6182
case invalid

test/FixCode/fixits-apply.swift.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ func testMask5(a: Int) {
5656
func testMask6(a: Int) {
5757
sendItOpt(MyEventMask2(rawValue: UInt64(a)))
5858
}
59+
func testMask7(a: Int?) {
60+
sendItOpt(a.map{ MyEventMask2(rawValue: UInt64($0)) })
61+
}
62+
func testMask8(a: UInt64?) {
63+
sendItOpt(a.map{ MyEventMask2(rawValue: $0) })
64+
}
65+
func testMask9(a: Any) {
66+
sendItOpt((a as? Int).map{ MyEventMask2(rawValue: UInt64($0)) })
67+
}
68+
func testMask10(a: Int?) {
69+
sendIt(a) // no fix, nullability mismatch.
70+
}
71+
func testMask11(a: MyEventMask2?) {
72+
testMask7(a: a.map{ UInt64($0.rawValue) })
73+
}
74+
func testMask12(a: MyEventMask2?) {
75+
testMask8(a: a.map{ $0.rawValue })
76+
}
77+
func testMask13(a: MyEventMask2?) {
78+
testMask1(a: a) // no fix, nullability mismatch.
79+
}
5980

6081
enum MyEnumType : UInt32 {
6182
case invalid

0 commit comments

Comments
 (0)