Skip to content

Commit 7ffa261

Browse files
authored
Merge pull request #73151 from jckarter/borrowing-switch-old-behavior-compat-6.0
[6.0] SILGen: Provide compatibility with prior `BorrowingSwitch` behavior.
2 parents a8e804a + d1b9dd0 commit 7ffa261

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
#include "DefineDiagnosticMacros.h"
2222

2323
// SILGen issues.
24+
WARNING(return_borrowing_switch_binding,none,
25+
"returning the non-'Copyable' value of a pattern binding from a "
26+
"switch that borrows by default; the switch will be performed as a "
27+
"consume for compatibility for now, but this will require an explicit "
28+
"'switch consume' in the future", ())
29+
2430
ERROR(bridging_module_missing,none,
2531
"unable to find module '%0' for implicit conversion function '%0.%1'",
2632
(StringRef, StringRef))

lib/SILGen/SILGenPattern.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3366,6 +3366,32 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
33663366
for (auto item : caseLabel->getCaseLabelItems()) {
33673367
ownership = std::max(ownership, item.getPattern()->getOwnership());
33683368
}
3369+
// To help migrate early adopters of the feature, if the case body is
3370+
// obviously trying to return out one of the pattern bindings, which
3371+
// would necessitate a consuming switch, perform the switch as a consume,
3372+
// and warn that this will need to be made explicit in the future.
3373+
if (ownership == ValueOwnership::Shared) {
3374+
if (auto ret = dyn_cast_or_null<ReturnStmt>(
3375+
caseLabel->getBody()->getSingleActiveElement()
3376+
.dyn_cast<Stmt*>())) {
3377+
Expr *result = ret->getResult()->getSemanticsProvidingExpr();
3378+
if (result->getType()->isNoncopyable()) {
3379+
while (auto conv = dyn_cast<ImplicitConversionExpr>(result)) {
3380+
result = conv->getSubExpr()->getSemanticsProvidingExpr();
3381+
}
3382+
if (auto dr = dyn_cast<DeclRefExpr>(result)) {
3383+
if (std::find(caseLabel->getCaseBodyVariables().begin(),
3384+
caseLabel->getCaseBodyVariables().end(),
3385+
dr->getDecl())
3386+
!= caseLabel->getCaseBodyVariables().end()) {
3387+
SGM.diagnose(result->getLoc(),
3388+
diag::return_borrowing_switch_binding);
3389+
ownership = ValueOwnership::Owned;
3390+
}
3391+
}
3392+
}
3393+
}
3394+
}
33693395
}
33703396
}
33713397

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-emit-silgen -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BorrowingSwitch -verify %s
2+
func orElse<T: ~Copyable>(
3+
x: consuming T?,
4+
defaultValue: @autoclosure () throws -> T?
5+
) rethrows -> T? {
6+
switch x {
7+
case .some(let value):
8+
return value // expected-warning{{returning the non-'Copyable' value of a pattern binding from a switch that borrows by default}}
9+
case .none:
10+
return try defaultValue()
11+
}
12+
}

0 commit comments

Comments
 (0)