@@ -166,12 +166,6 @@ bool FailureDiagnostic::conformsToKnownProtocol(
166
166
return constraints::conformsToKnownProtocol (cs, type, protocol);
167
167
}
168
168
169
- Type FailureDiagnostic::isRawRepresentable (Type type,
170
- KnownProtocolKind protocol) const {
171
- auto &cs = getConstraintSystem ();
172
- return constraints::isRawRepresentable (cs, type, protocol);
173
- }
174
-
175
169
Type RequirementFailure::getOwnerType () const {
176
170
auto anchor = getRawAnchor ();
177
171
@@ -2297,12 +2291,6 @@ void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const {
2297
2291
if (trySequenceSubsequenceFixIts (diagnostic))
2298
2292
return ;
2299
2293
2300
- if (tryRawRepresentableFixIts (
2301
- diagnostic, KnownProtocolKind::ExpressibleByIntegerLiteral) ||
2302
- tryRawRepresentableFixIts (diagnostic,
2303
- KnownProtocolKind::ExpressibleByStringLiteral))
2304
- return ;
2305
-
2306
2294
if (tryIntegerCastFixIts (diagnostic))
2307
2295
return ;
2308
2296
@@ -2532,130 +2520,6 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const {
2532
2520
return true ;
2533
2521
}
2534
2522
2535
- bool ContextualFailure::tryRawRepresentableFixIts (
2536
- InFlightDiagnostic &diagnostic,
2537
- KnownProtocolKind rawRepresentableProtocol) const {
2538
- auto anchor = getAnchor ();
2539
- auto fromType = getFromType ();
2540
- auto toType = getToType ();
2541
-
2542
- // The following fixes apply for optional destination types as well.
2543
- bool toTypeIsOptional = !toType->getOptionalObjectType ().isNull ();
2544
- toType = toType->lookThroughAllOptionalTypes ();
2545
-
2546
- Type fromTypeUnwrapped = fromType->getOptionalObjectType ();
2547
- bool fromTypeIsOptional = !fromTypeUnwrapped.isNull ();
2548
- if (fromTypeIsOptional)
2549
- fromType = fromTypeUnwrapped;
2550
-
2551
- auto fixIt = [&](StringRef convWrapBefore, StringRef convWrapAfter,
2552
- const Expr *expr) {
2553
- SourceRange exprRange = expr->getSourceRange ();
2554
- if (fromTypeIsOptional && toTypeIsOptional) {
2555
- // Use optional's map function to convert conditionally, like so:
2556
- // expr.map{ T(rawValue: $0) }
2557
- bool needsParens = !expr->canAppendPostfixExpression ();
2558
- std::string mapCodeFix;
2559
- if (needsParens) {
2560
- diagnostic.fixItInsert (exprRange.Start , " (" );
2561
- mapCodeFix += " )" ;
2562
- }
2563
- mapCodeFix += " .map { " ;
2564
- mapCodeFix += convWrapBefore;
2565
- mapCodeFix += " $0" ;
2566
- mapCodeFix += convWrapAfter;
2567
- mapCodeFix += " }" ;
2568
- diagnostic.fixItInsertAfter (exprRange.End , mapCodeFix);
2569
- } else if (!fromTypeIsOptional) {
2570
- diagnostic.fixItInsert (exprRange.Start , convWrapBefore);
2571
- diagnostic.fixItInsertAfter (exprRange.End , convWrapAfter);
2572
- } else {
2573
- SmallString<16 > fixItBefore (convWrapBefore);
2574
- SmallString<16 > fixItAfter;
2575
-
2576
- if (!expr->canAppendPostfixExpression (true )) {
2577
- fixItBefore += " (" ;
2578
- fixItAfter = " )" ;
2579
- }
2580
-
2581
- fixItAfter += " !" + convWrapAfter.str ();
2582
-
2583
- diagnostic.flush ();
2584
- emitDiagnostic (diag::construct_raw_representable_from_unwrapped_value,
2585
- toType, fromType)
2586
- .highlight (exprRange)
2587
- .fixItInsert (exprRange.Start , fixItBefore)
2588
- .fixItInsertAfter (exprRange.End , fixItAfter);
2589
- }
2590
- };
2591
-
2592
- if (conformsToKnownProtocol (fromType, rawRepresentableProtocol)) {
2593
- if (conformsToKnownProtocol (fromType, KnownProtocolKind::OptionSet) &&
2594
- isExpr<IntegerLiteralExpr>(anchor) &&
2595
- castToExpr<IntegerLiteralExpr>(anchor)->getDigitsText () == " 0" ) {
2596
- diagnostic.fixItReplace (::getSourceRange (anchor), " []" );
2597
- return true ;
2598
- }
2599
- if (auto rawTy = isRawRepresentable (toType, rawRepresentableProtocol)) {
2600
- // Produce before/after strings like 'Result(rawValue: RawType(<expr>))'
2601
- // or just 'Result(rawValue: <expr>)'.
2602
- std::string convWrapBefore = toType.getString ();
2603
- convWrapBefore += " (rawValue: " ;
2604
- std::string convWrapAfter = " )" ;
2605
- if (!isExpr<LiteralExpr>(anchor) &&
2606
- !TypeChecker::isConvertibleTo (fromType, rawTy, getDC ())) {
2607
- // Only try to insert a converting construction if the protocol is a
2608
- // literal protocol and not some other known protocol.
2609
- switch (rawRepresentableProtocol) {
2610
- #define EXPRESSIBLE_BY_LITERAL_PROTOCOL_WITH_NAME (name, _, __, ___ ) \
2611
- case KnownProtocolKind::name: \
2612
- break ;
2613
- #define PROTOCOL_WITH_NAME (name, _ ) \
2614
- case KnownProtocolKind::name: \
2615
- return false ;
2616
- #include " swift/AST/KnownProtocols.def"
2617
- }
2618
- convWrapBefore += rawTy->getString ();
2619
- convWrapBefore += " (" ;
2620
- convWrapAfter += " )" ;
2621
- }
2622
-
2623
- if (auto *E = getAsExpr (anchor))
2624
- fixIt (convWrapBefore, convWrapAfter, E);
2625
- return true ;
2626
- }
2627
- }
2628
-
2629
- if (auto rawTy = isRawRepresentable (fromType, rawRepresentableProtocol)) {
2630
- if (conformsToKnownProtocol (toType, rawRepresentableProtocol)) {
2631
- std::string convWrapBefore;
2632
- std::string convWrapAfter = " .rawValue" ;
2633
- if (!TypeChecker::isConvertibleTo (rawTy, toType, getDC ())) {
2634
- // Only try to insert a converting construction if the protocol is a
2635
- // literal protocol and not some other known protocol.
2636
- switch (rawRepresentableProtocol) {
2637
- #define EXPRESSIBLE_BY_LITERAL_PROTOCOL_WITH_NAME (name, _, __, ___ ) \
2638
- case KnownProtocolKind::name: \
2639
- break ;
2640
- #define PROTOCOL_WITH_NAME (name, _ ) \
2641
- case KnownProtocolKind::name: \
2642
- return false ;
2643
- #include " swift/AST/KnownProtocols.def"
2644
- }
2645
- convWrapBefore += toType->getString ();
2646
- convWrapBefore += " (" ;
2647
- convWrapAfter += " )" ;
2648
- }
2649
-
2650
- if (auto *E = getAsExpr (anchor))
2651
- fixIt (convWrapBefore, convWrapAfter, E);
2652
- return true ;
2653
- }
2654
- }
2655
-
2656
- return false ;
2657
- }
2658
-
2659
2523
bool ContextualFailure::tryIntegerCastFixIts (
2660
2524
InFlightDiagnostic &diagnostic) const {
2661
2525
auto fromType = getFromType ();
@@ -6389,3 +6253,136 @@ bool UnableToInferKeyPathRootFailure::diagnoseAsError() {
6389
6253
.fixItInsertAfter (keyPathExpr->getStartLoc (), " <#Root#>" );
6390
6254
return true ;
6391
6255
}
6256
+
6257
+ Optional<Diag<Type, Type>>
6258
+ AbstractRawRepresentableFailure::getDiagnostic () const {
6259
+ auto *locator = getLocator ();
6260
+
6261
+ if (locator->isForContextualType ()) {
6262
+ return diag::cannot_convert_initializer_value;
6263
+ } else if (locator->isForAssignment ()) {
6264
+ return diag::cannot_convert_assign;
6265
+ } else if (locator->isLastElement <LocatorPathElt::ApplyArgToParam>()) {
6266
+ return diag::cannot_convert_argument_value;
6267
+ }
6268
+
6269
+ return None;
6270
+ }
6271
+
6272
+ bool AbstractRawRepresentableFailure::diagnoseAsError () {
6273
+ auto message = getDiagnostic ();
6274
+ if (!message)
6275
+ return false ;
6276
+
6277
+ auto diagnostic = emitDiagnostic (*message, getFromType (), getToType ());
6278
+ fixIt (diagnostic);
6279
+ return true ;
6280
+ }
6281
+
6282
+ bool AbstractRawRepresentableFailure::diagnoseAsNote () {
6283
+ auto *locator = getLocator ();
6284
+
6285
+ Optional<InFlightDiagnostic> diagnostic;
6286
+ if (locator->isForContextualType ()) {
6287
+ auto overload = getCalleeOverloadChoiceIfAvailable (locator);
6288
+ if (!overload)
6289
+ return false ;
6290
+
6291
+ if (auto *decl = overload->choice .getDeclOrNull ()) {
6292
+ diagnostic.emplace (emitDiagnosticAt (
6293
+ decl, diag::cannot_convert_candidate_result_to_contextual_type,
6294
+ decl->getName (), ExpectedType, RawReprType));
6295
+ }
6296
+ } else if (auto argConv =
6297
+ locator->getLastElementAs <LocatorPathElt::ApplyArgToParam>()) {
6298
+ diagnostic.emplace (
6299
+ emitDiagnostic (diag::candidate_has_invalid_argument_at_position,
6300
+ RawReprType, argConv->getParamIdx (), /* inOut=*/ false ));
6301
+ }
6302
+
6303
+ if (diagnostic) {
6304
+ fixIt (*diagnostic);
6305
+ return true ;
6306
+ }
6307
+
6308
+ return false ;
6309
+ }
6310
+
6311
+ void MissingRawRepresentableInitFailure::fixIt (
6312
+ InFlightDiagnostic &diagnostic) const {
6313
+ if (auto *E = getAsExpr (getAnchor ())) {
6314
+ auto range = E->getSourceRange ();
6315
+ auto rawReprObjType = RawReprType->getOptionalObjectType ();
6316
+ auto valueObjType = ExpectedType->getOptionalObjectType ();
6317
+
6318
+ if (rawReprObjType && valueObjType) {
6319
+ std::string mapCodeFix;
6320
+
6321
+ // Check whether expression has been be wrapped in parens first.
6322
+ if (!E->canAppendPostfixExpression ()) {
6323
+ diagnostic.fixItInsert (range.Start , " (" );
6324
+ mapCodeFix += " )" ;
6325
+ }
6326
+
6327
+ mapCodeFix += " .map { " ;
6328
+ mapCodeFix += rawReprObjType->getString ();
6329
+ mapCodeFix += " (rawValue: $0) }" ;
6330
+
6331
+ diagnostic.fixItInsertAfter (range.End , mapCodeFix);
6332
+ } else if (rawReprObjType) {
6333
+ diagnostic
6334
+ .fixItInsert (range.Start , rawReprObjType->getString () + " (rawValue: " )
6335
+ .fixItInsertAfter (range.End , " )" );
6336
+ } else if (valueObjType) {
6337
+ diagnostic.flush ();
6338
+
6339
+ std::string fixItBefore = RawReprType->getString () + " (rawValue: " ;
6340
+ std::string fixItAfter;
6341
+
6342
+ if (!E->canAppendPostfixExpression (true )) {
6343
+ fixItBefore += " (" ;
6344
+ fixItAfter += " )" ;
6345
+ }
6346
+
6347
+ fixItAfter += " !) ?? <#default value#>" ;
6348
+
6349
+ emitDiagnostic (diag::construct_raw_representable_from_unwrapped_value,
6350
+ RawReprType, valueObjType)
6351
+ .highlight (range)
6352
+ .fixItInsert (range.Start , fixItBefore)
6353
+ .fixItInsertAfter (range.End , fixItAfter);
6354
+ } else {
6355
+ diagnostic
6356
+ .fixItInsert (range.Start , RawReprType->getString () + " (rawValue: " )
6357
+ .fixItInsertAfter (range.End , " ) ?? <#default value#>" );
6358
+ }
6359
+ }
6360
+ }
6361
+
6362
+ void MissingRawValueFailure::fixIt (InFlightDiagnostic &diagnostic) const {
6363
+ auto *E = getAsExpr (getAnchor ());
6364
+ if (!E)
6365
+ return ;
6366
+
6367
+ std::string fix;
6368
+
6369
+ auto range = E->getSourceRange ();
6370
+ if (!E->canAppendPostfixExpression ()) {
6371
+ diagnostic.fixItInsert (range.Start , " (" );
6372
+ fix += " )" ;
6373
+ }
6374
+
6375
+ // If raw representable is an optional we need to map its raw value out
6376
+ // out first and then, if destination is not optional, allow to specify
6377
+ // default value.
6378
+ if (RawReprType->getOptionalObjectType ()) {
6379
+ fix += " ?.rawValue" ;
6380
+
6381
+ if (!ExpectedType->getOptionalObjectType ())
6382
+ fix += " ?? <#default value#>" ;
6383
+ } else {
6384
+ fix += " .rawValue" ;
6385
+ }
6386
+
6387
+ diagnostic.fixItInsertAfter (range.End , fix);
6388
+ }
0 commit comments