Skip to content

Commit 43a582e

Browse files
committed
Initial implementation of optionals-in-string-interpolation warnings
Basic extension of the optional-to-any AST walker to incorporate warnings for the as-of-now up and coming Swift evolution proposal.
1 parent 0e3740c commit 43a582e

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,12 +2405,16 @@ WARNING(optional_pattern_match_promotion,none,
24052405
(Type, Type))
24062406
WARNING(optional_to_any_coercion,none,
24072407
"expression implicitly coerced from %0 to Any", (Type))
2408+
WARNING(optional_in_string_interpolation_segment,none,
2409+
"string interpolation of optional can have unintended effects", ())
24082410
NOTE(default_optional_to_any,none,
24092411
"provide a default value to avoid this warning", ())
24102412
NOTE(force_optional_to_any,none,
24112413
"force-unwrap the value to avoid this warning", ())
24122414
NOTE(silence_optional_to_any,none,
24132415
"explicitly cast to Any with 'as Any' to silence this warning", ())
2416+
NOTE(silence_optional_in_interpolation_segment,none,
2417+
"explicitly use '.debugDescription' to silence this warning", ())
24142418

24152419
ERROR(invalid_noescape_use,none,
24162420
"non-escaping %select{value|parameter}1 %0 may only be called",

lib/Sema/MiscDiagnostics.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3707,8 +3707,33 @@ static void diagnoseOptionalToAnyCoercion(TypeChecker &TC, const Expr *E,
37073707
.highlight(subExpr->getSourceRange())
37083708
.fixItInsertAfter(subExpr->getEndLoc(), " as Any");
37093709
}
3710-
}
3710+
} else if (auto *literal = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
3711+
// Warn about interpolated segments that contain optionals.
3712+
for (auto &segment : literal->getSegments()) {
3713+
// Allow explicit casts.
3714+
if (isa<ExplicitCastExpr>(segment)) {
3715+
continue;
3716+
}
37113717

3718+
auto segmentTy = segment->getType();
3719+
if (segmentTy && !segmentTy->getOptionalObjectType().isNull()) {
3720+
TC.diagnose(segment->getStartLoc(),
3721+
diag::optional_in_string_interpolation_segment)
3722+
.highlight(segment->getSourceRange());
3723+
3724+
TC.diagnose(segment->getLoc(),
3725+
diag::silence_optional_in_interpolation_segment)
3726+
.highlight(segment->getSourceRange())
3727+
.fixItInsertAfter(segment->getEndLoc(), ".debugDescription");
3728+
TC.diagnose(segment->getLoc(), diag::default_optional_to_any)
3729+
.highlight(segment->getSourceRange())
3730+
.fixItInsertAfter(segment->getEndLoc(), " ?? <#default value#>");
3731+
TC.diagnose(segment->getLoc(), diag::force_optional_to_any)
3732+
.highlight(segment->getSourceRange())
3733+
.fixItInsertAfter(segment->getEndLoc(), "!");
3734+
}
3735+
}
3736+
}
37123737
return { true, E };
37133738
}
37143739

0 commit comments

Comments
 (0)