@@ -3096,6 +3096,63 @@ static bool isIntegerToStringIndexConversion(Type fromType, Type toType,
3096
3096
return false ;
3097
3097
}
3098
3098
3099
+ static void tryConversionFixit (InFlightDiagnostic &diag,
3100
+ ConstraintSystem *CS,
3101
+ Diag<Type, Type> diagID,
3102
+ Type exprType,
3103
+ Type contextualType,
3104
+ Expr *expr) {
3105
+ if (!CS || !expr || !exprType || !contextualType)
3106
+ return ;
3107
+ if (diagID.ID != diag::cannot_convert_argument_value.ID )
3108
+ return ;
3109
+
3110
+ auto integerType =
3111
+ CS->TC .getProtocol (SourceLoc (),
3112
+ KnownProtocolKind::IntegerLiteralConvertible);
3113
+ if (!integerType) return ;
3114
+
3115
+ auto isIntegerType = [&](Type ty) -> bool {
3116
+ return CS->TC .conformsToProtocol (exprType, integerType, CS->DC ,
3117
+ ConformanceCheckFlags::InExpression);
3118
+ };
3119
+
3120
+ // When the error is "cannot convert value of type <integer> to expected
3121
+ // argument type <RawRepresentable>", add a fixit that constructs the
3122
+ // raw-representable type from the value. This helps with SDK changes.
3123
+
3124
+ if (!isIntegerType (exprType))
3125
+ return ;
3126
+
3127
+ auto rawReprType =
3128
+ CS->TC .getProtocol (SourceLoc (), KnownProtocolKind::RawRepresentable);
3129
+ if (!rawReprType) return ;
3130
+
3131
+ ProtocolConformance *rawReprConformance;
3132
+ if (!CS->TC .conformsToProtocol (contextualType, rawReprType, CS->DC ,
3133
+ ConformanceCheckFlags::InExpression,
3134
+ &rawReprConformance))
3135
+ return ;
3136
+
3137
+ Type rawTy = ProtocolConformance::getTypeWitnessByName (contextualType,
3138
+ rawReprConformance,
3139
+ CS->getASTContext ().getIdentifier (" RawValue" ),
3140
+ &CS->TC );
3141
+ if (!rawTy || !isIntegerType (rawTy))
3142
+ return ;
3143
+
3144
+ std::string convWrapBefore = contextualType.getString ();
3145
+ convWrapBefore += " (rawValue: " ;
3146
+ std::string convWrapAfter = " )" ;
3147
+ if (rawTy->getCanonicalType () != exprType->getCanonicalType ()) {
3148
+ convWrapBefore += rawTy->getString ();
3149
+ convWrapBefore += " (" ;
3150
+ convWrapAfter += " )" ;
3151
+ }
3152
+ SourceRange exprRange = expr->getSourceRange ();
3153
+ diag.fixItInsert (exprRange.Start , convWrapBefore);
3154
+ diag.fixItInsertAfter (exprRange.End , convWrapAfter);
3155
+ }
3099
3156
3100
3157
bool FailureDiagnosis::diagnoseContextualConversionError () {
3101
3158
// If the constraint system has a contextual type, then we can test to see if
@@ -3325,8 +3382,9 @@ bool FailureDiagnosis::diagnoseContextualConversionError() {
3325
3382
diagID = diag::noescape_functiontype_mismatch;
3326
3383
}
3327
3384
3328
- diagnose (expr->getLoc (), diagID, exprType, contextualType)
3329
- .highlight (expr->getSourceRange ());
3385
+ InFlightDiagnostic diag = diagnose (expr->getLoc (), diagID, exprType, contextualType);
3386
+ diag.highlight (expr->getSourceRange ());
3387
+ tryConversionFixit (diag, CS, diagID, exprType, contextualType, expr);
3330
3388
return true ;
3331
3389
}
3332
3390
0 commit comments