Skip to content

Commit 3d1ff4d

Browse files
authored
Merge pull request #3749 from nkcsgexi/coerce-fixit
2 parents 03d88c6 + fc8a1d2 commit 3d1ff4d

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,8 +3407,10 @@ static bool isIntegerToStringIndexConversion(Type fromType, Type toType,
34073407
/// expected, by wrapping the expression in a call to the rawValue
34083408
/// accessor
34093409
///
3410+
/// - Return true on the fixit is added, false otherwise.
3411+
///
34103412
/// This helps migration with SDK changes.
3411-
static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
3413+
static bool tryRawRepresentableFixIts(InFlightDiagnostic &diag,
34123414
ConstraintSystem *CS,
34133415
Type fromType,
34143416
Type toType,
@@ -3459,7 +3461,7 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
34593461
convWrapAfter += ")";
34603462
}
34613463
fixIt(convWrapBefore, convWrapAfter);
3462-
return;
3464+
return true;
34633465
}
34643466
}
34653467

@@ -3473,9 +3475,10 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
34733475
convWrapAfter += ")";
34743476
}
34753477
fixIt(convWrapBefore, convWrapAfter);
3476-
return;
3478+
return true;
34773479
}
34783480
}
3481+
return false;
34793482
}
34803483

34813484
/// Attempts to add fix-its for these two mistakes:
@@ -3486,14 +3489,16 @@ static void tryRawRepresentableFixIts(InFlightDiagnostic &diag,
34863489
/// - Passing an integer but expecting different integer type. The fixit adds
34873490
/// a wrapping cast.
34883491
///
3492+
/// - Return true on the fixit is added, false otherwise.
3493+
///
34893494
/// This helps migration with SDK changes.
3490-
static void tryIntegerCastFixIts(InFlightDiagnostic &diag,
3495+
static bool tryIntegerCastFixIts(InFlightDiagnostic &diag,
34913496
ConstraintSystem *CS,
34923497
Type fromType,
34933498
Type toType,
34943499
Expr *expr) {
34953500
if (!isIntegerType(fromType, CS) || !isIntegerType(toType, CS))
3496-
return;
3501+
return false;
34973502

34983503
auto getInnerCastedExpr = [&]() -> Expr* {
34993504
CallExpr *CE = dyn_cast<CallExpr>(expr);
@@ -3513,7 +3518,7 @@ static void tryIntegerCastFixIts(InFlightDiagnostic &diag,
35133518
// Remove the unnecessary cast.
35143519
diag.fixItRemoveChars(expr->getLoc(), innerE->getStartLoc())
35153520
.fixItRemove(expr->getEndLoc());
3516-
return;
3521+
return true;
35173522
}
35183523
}
35193524

@@ -3524,6 +3529,24 @@ static void tryIntegerCastFixIts(InFlightDiagnostic &diag,
35243529
SourceRange exprRange = expr->getSourceRange();
35253530
diag.fixItInsert(exprRange.Start, convWrapBefore);
35263531
diag.fixItInsertAfter(exprRange.End, convWrapAfter);
3532+
return true;
3533+
}
3534+
3535+
static bool
3536+
addTypeCoerceFixit(InFlightDiagnostic &diag, ConstraintSystem *CS,
3537+
Type fromType, Type toType, Expr *expr) {
3538+
if (CS->getTypeChecker().typeCheckCheckedCast(fromType, toType, CS->DC,
3539+
SourceLoc(), SourceRange(), SourceRange(), [](Type T) { return false; },
3540+
true) != CheckedCastKind::Unresolved) {
3541+
SmallString<32> buffer;
3542+
llvm::raw_svector_ostream OS(buffer);
3543+
toType->print(OS);
3544+
diag.fixItInsert(Lexer::getLocForEndOfToken(CS->DC->getASTContext().SourceMgr,
3545+
expr->getEndLoc()),
3546+
(llvm::Twine(" as! ") + OS.str()).str());
3547+
return true;
3548+
}
3549+
return false;
35273550
}
35283551

35293552
bool FailureDiagnosis::diagnoseContextualConversionError() {
@@ -3800,11 +3823,12 @@ bool FailureDiagnosis::diagnoseContextualConversionError() {
38003823
case CTP_DictionaryValue:
38013824
tryRawRepresentableFixIts(diag, CS, exprType, contextualType,
38023825
KnownProtocolKind::ExpressibleByIntegerLiteral,
3803-
expr);
3826+
expr) ||
38043827
tryRawRepresentableFixIts(diag, CS, exprType, contextualType,
38053828
KnownProtocolKind::ExpressibleByStringLiteral,
3806-
expr);
3807-
tryIntegerCastFixIts(diag, CS, exprType, contextualType, expr);
3829+
expr) ||
3830+
tryIntegerCastFixIts(diag, CS, exprType, contextualType, expr) ||
3831+
addTypeCoerceFixit(diag, CS, exprType, contextualType, expr);
38083832
break;
38093833

38103834
default:

test/Sema/diag_type_conversion.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,22 @@ func foo3 () {
1515
foo2(1) // expected-error {{cannot convert value of type 'Int' to expected argument type 'UnsafePointer<Int>'}} {{none}}
1616
foo4(1) // expected-error {{cannot convert value of type 'Int' to expected argument type 'UnsafeMutablePointer<Int>'}} {{none}}
1717
}
18+
19+
class A {}
20+
class B : A {}
21+
func foo5(b : B) {}
22+
func foo6(a : A) {
23+
foo5(b : a) // expected-error {{cannot convert value of type 'A' to expected argument type 'B'}} {{13-13= as! B}}
24+
}
25+
26+
func foo7(b : [B]) {}
27+
func foo8(a : [A]) {
28+
foo7(b : a) // expected-error {{cannot convert value of type '[A]' to expected argument type '[B]'}} {{13-13= as! [B]}}
29+
}
30+
31+
protocol P1 {}
32+
struct S1 : P1 {}
33+
func foo9(s : S1) {}
34+
func foo10(p : P1) {
35+
foo9(s : p) // expected-error {{cannot convert value of type 'P1' to expected argument type 'S1'}} {{13-13= as! S1}}
36+
}

0 commit comments

Comments
 (0)