Skip to content

Commit 1b901a9

Browse files
committed
Sema: Optional-promote tuple patterns during solution application
1 parent 236e88d commit 1b901a9

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4635,8 +4635,9 @@ WARNING(found_one_pattern_for_several_associated_values,Deprecation,
46354635
WARNING(converting_tuple_into_several_associated_values,none,
46364636
"enum case '%0' has %1 associated values", (StringRef, unsigned))
46374637
WARNING(converting_several_associated_values_into_tuple,none,
4638-
"enum case '%0' has one associated value that is a tuple of %1 "
4639-
"elements",(StringRef, unsigned))
4638+
"enum case '%0' has one associated value that is a %select{|optional }1"
4639+
"tuple of %2 elements",
4640+
(StringRef, bool, unsigned))
46404641
ERROR(closure_argument_list_tuple,none,
46414642
"contextual closure type %0 expects %1 argument%s1, "
46424643
"but %2 %select{were|was}3 used in closure body", (Type, unsigned, unsigned, bool))

lib/Sema/TypeCheckPattern.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ Type PatternTypeRequest::evaluate(Evaluator &evaluator,
954954
/// "repair" the pattern if needed. This ensures that the pattern engine
955955
/// receives well-formed input, avoiding the need to implement an additional
956956
/// compatibility hack there, as doing that is lot more tricky due to the
957-
/// different cases that need to handled.
957+
/// different cases that need to be handled.
958958
///
959959
/// We also emit diagnostics and potentially a fix-it to help the user.
960960
///
@@ -1011,12 +1011,16 @@ void repairTupleOrAssociatedValuePatternIfApplicable(
10111011
addDeclNote = true;
10121012
}
10131013
}
1014-
} else if (auto *tupleType = enumPayloadType->getAs<TupleType>()) {
1014+
} else if (auto *tupleType = enumPayloadType
1015+
// Account for implicit optional promotion.
1016+
->lookThroughAllOptionalTypes()
1017+
->getAs<TupleType>()) {
10151018
if (tupleType->getNumElements() >= 2) {
10161019
if (auto *tuplePattern = dyn_cast<TuplePattern>(enumElementInnerPat)) {
10171020
DE.diagnose(enumElementInnerPat->getLoc(),
10181021
diag::converting_several_associated_values_into_tuple,
10191022
enumCase->getNameStr(),
1023+
enumPayloadType->isOptional(),
10201024
tupleType->getNumElements())
10211025
.fixItInsert(enumElementInnerPat->getStartLoc(), "(")
10221026
.fixItInsertAfter(enumElementInnerPat->getEndLoc(), ")");
@@ -1237,6 +1241,21 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
12371241
return P;
12381242
}
12391243

1244+
// Allow optional promotion only when pattern matching is allowed to
1245+
// fail (in statement conditions, 'switch' case items, but not pattern
1246+
// binding declarations).
1247+
const bool allowOptionalPromotion = !pattern.getPatternBindingDecl();
1248+
1249+
const auto origTy = type;
1250+
if (allowOptionalPromotion) {
1251+
// Peel away any optionality. If the coercion succeeds, we will promote
1252+
// the resulting pattern to the original type by wrapping it in
1253+
// 'OptionalSome' patterns.
1254+
type = type->lookThroughAllOptionalTypes();
1255+
}
1256+
1257+
tupleTy = type->getAs<TupleType>();
1258+
12401259
if (!tupleTy) {
12411260
diags.diagnose(TP->getStartLoc(),
12421261
diag::tuple_pattern_in_non_tuple_context, type);
@@ -1278,6 +1297,21 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
12781297
}
12791298

12801299
P->setType(type);
1300+
1301+
if (allowOptionalPromotion) {
1302+
// If the original coercion type is optional, promote the resulting
1303+
// pattern to a matching optionality.
1304+
if (auto wrappedTy = origTy->getOptionalObjectType()) {
1305+
do {
1306+
auto *OSP =
1307+
OptionalSomePattern::createImplicit(Context, P, P->getEndLoc());
1308+
OSP->setType(OptionalType::get(P->getType()));
1309+
P = OSP;
1310+
wrappedTy = wrappedTy->getOptionalObjectType();
1311+
} while (wrappedTy);
1312+
}
1313+
}
1314+
12811315
return P;
12821316
}
12831317

0 commit comments

Comments
 (0)