Skip to content

Commit f36cc94

Browse files
committed
[FixCode] Add fix-its for mismatched integer types.
Adds fixits for: - Passing an integer with the right type but which is getting wrapped with a different integer type unnecessarily. The fixit removes the cast. - Passing an integer but expecting different integer type. The fixit adds a wrapping cast.
1 parent 2848482 commit f36cc94

File tree

3 files changed

+73
-3
lines changed

3 files changed

+73
-3
lines changed

Diff for: lib/Sema/CSDiag.cpp

+57-3
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,12 @@ static bool isLiteralConvertibleType(Type fromType,
30933093
return false;
30943094
}
30953095

3096+
static bool isIntegerType(Type fromType, ConstraintSystem *CS) {
3097+
return isLiteralConvertibleType(fromType,
3098+
KnownProtocolKind::IntegerLiteralConvertible,
3099+
CS);
3100+
}
3101+
30963102
/// Return true if the given type conforms to RawRepresentable, with an
30973103
/// underlying type conforming to the given known protocol.
30983104
static Type isRawRepresentable(Type fromType,
@@ -3141,7 +3147,6 @@ static bool isIntegerToStringIndexConversion(Type fromType, Type toType,
31413147
/// This helps migration with SDK changes.
31423148
static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
31433149
ConstraintSystem *CS,
3144-
Diag<Type, Type> diagID,
31453150
Type fromType,
31463151
Type toType,
31473152
KnownProtocolKind kind,
@@ -3182,6 +3187,54 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
31823187
}
31833188
}
31843189

3190+
/// Attempts to add fix-its for these two mistakes:
3191+
///
3192+
/// - Passing an integer with the right type but which is getting wrapped with a
3193+
/// different integer type unnecessarily. The fixit removes the cast.
3194+
///
3195+
/// - Passing an integer but expecting different integer type. The fixit adds
3196+
/// a wrapping cast.
3197+
///
3198+
/// This helps migration with SDK changes.
3199+
static void tryIntegerCastFixIts(InFlightDiagnostic &diag,
3200+
ConstraintSystem *CS,
3201+
Type fromType,
3202+
Type toType,
3203+
Expr *expr) {
3204+
if (!isIntegerType(fromType, CS) || !isIntegerType(toType, CS))
3205+
return;
3206+
3207+
auto getInnerCastedExpr = [&]() -> Expr* {
3208+
CallExpr *CE = dyn_cast<CallExpr>(expr);
3209+
if (!CE)
3210+
return nullptr;
3211+
if (!isa<ConstructorRefCallExpr>(CE->getFn()))
3212+
return nullptr;
3213+
ParenExpr *parenE = dyn_cast<ParenExpr>(CE->getArg());
3214+
if (!parenE)
3215+
return nullptr;
3216+
return parenE->getSubExpr();
3217+
};
3218+
3219+
if (Expr *innerE = getInnerCastedExpr()) {
3220+
Type innerTy = innerE->getType();
3221+
if (CS->TC.isConvertibleTo(innerTy, toType, CS->DC)) {
3222+
// Remove the unnecessary cast.
3223+
diag.fixItRemoveChars(expr->getLoc(), innerE->getStartLoc())
3224+
.fixItRemove(expr->getEndLoc());
3225+
return;
3226+
}
3227+
}
3228+
3229+
// Add a wrapping integer cast.
3230+
std::string convWrapBefore = toType.getString();
3231+
convWrapBefore += "(";
3232+
std::string convWrapAfter = ")";
3233+
SourceRange exprRange = expr->getSourceRange();
3234+
diag.fixItInsert(exprRange.Start, convWrapBefore);
3235+
diag.fixItInsertAfter(exprRange.End, convWrapAfter);
3236+
}
3237+
31853238
bool FailureDiagnosis::diagnoseContextualConversionError() {
31863239
// If the constraint system has a contextual type, then we can test to see if
31873240
// this is the problem that prevents us from solving the system.
@@ -3420,12 +3473,13 @@ bool FailureDiagnosis::diagnoseContextualConversionError() {
34203473
case CTP_ArrayElement:
34213474
case CTP_DictionaryKey:
34223475
case CTP_DictionaryValue:
3423-
tryRawRepresentableFixIts(diag, CS, diagID, exprType, contextualType,
3476+
tryRawRepresentableFixIts(diag, CS, exprType, contextualType,
34243477
KnownProtocolKind::IntegerLiteralConvertible,
34253478
expr);
3426-
tryRawRepresentableFixIts(diag, CS, diagID, exprType, contextualType,
3479+
tryRawRepresentableFixIts(diag, CS, exprType, contextualType,
34273480
KnownProtocolKind::StringLiteralConvertible,
34283481
expr);
3482+
tryIntegerCastFixIts(diag, CS, exprType, contextualType, expr);
34293483
break;
34303484

34313485
default:

Diff for: test/FixCode/fixits-apply.swift

+8
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,11 @@ class SubTest2 : Test2 {
104104
}
105105
Test2().instMeth(0)
106106
Test2().instMeth2(0, p2:1)
107+
108+
func recit(_: Int32) {}
109+
func ftest3(_ fd: CInt) {
110+
recit(UInt(fd))
111+
}
112+
func ftest4(_ fd: UInt) {
113+
recit(fd)
114+
}

Diff for: test/FixCode/fixits-apply.swift.result

+8
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,11 @@ class SubTest2 : Test2 {
107107
}
108108
Test2().instMeth(0)
109109
Test2().instMeth2(0, p2:1)
110+
111+
func recit(_: Int32) {}
112+
func ftest3(_ fd: CInt) {
113+
recit(fd)
114+
}
115+
func ftest4(_ fd: UInt) {
116+
recit(Int32(fd))
117+
}

0 commit comments

Comments
 (0)