Skip to content

[6.0] Enable 'BorrowingSwitch' feature. #72984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ ERROR(extra_var_in_multiple_pattern_list,none,
ERROR(let_pattern_in_immutable_context,none,
"'let' pattern cannot appear nested in an already immutable context", ())
WARNING(borrowing_syntax_change,none,
"'_borrowing' spelling is deprecated; use 'borrowing' without the underscore", ())
"'borrowing' in pattern matches is deprecated; use 'let'", ())
ERROR(borrowing_subpattern_unsupported,none,
"'borrowing' pattern modifier must be directly applied to pattern variable name", ())
ERROR(specifier_must_have_type,none,
Expand Down
4 changes: 1 addition & 3 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ UPCOMING_FEATURE(ImplicitOpenExistentials, 352, 6)
UPCOMING_FEATURE(RegionBasedIsolation, 414, 6)
UPCOMING_FEATURE(DynamicActorIsolation, 423, 6)
UPCOMING_FEATURE(NonfrozenEnumExhaustivity, 192, 6)
UPCOMING_FEATURE(BorrowingSwitch, 432, 6)

// Swift 7
UPCOMING_FEATURE(ExistentialAny, 335, 7)
Expand Down Expand Up @@ -350,9 +351,6 @@ EXPERIMENTAL_FEATURE(GroupActorErrors, true)
// Allow for the 'transferring' keyword to be applied to arguments and results.
EXPERIMENTAL_FEATURE(TransferringArgsAndResults, true)

// Allow for `switch` of noncopyable values to be borrowing or consuming.
EXPERIMENTAL_FEATURE(BorrowingSwitch, true)

// Enable explicit isolation of closures.
EXPERIMENTAL_FEATURE(ClosureIsolation, true)

Expand Down
1 change: 0 additions & 1 deletion lib/ASTGen/Sources/ASTGen/SourceFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ extension Parser.ExperimentalFeatures {
mapFeature(.DoExpressions, to: .doExpressions)
mapFeature(.NonescapableTypes, to: .nonescapableTypes)
mapFeature(.TransferringArgsAndResults, to: .transferringArgsAndResults)
mapFeature(.BorrowingSwitch, to: .borrowingSwitch)
}
}

Expand Down
84 changes: 39 additions & 45 deletions lib/Parse/ParsePattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,45 +1351,41 @@ ParserResult<Pattern> Parser::parseMatchingPattern(bool isExprBasic) {

// The `borrowing` modifier is a contextual keyword, so it's only accepted
// directly applied to a binding name, as in `case .foo(borrowing x)`.
if (Context.LangOpts.hasFeature(Feature::BorrowingSwitch)) {
if ((Tok.isContextualKeyword("_borrowing")
|| Tok.isContextualKeyword("borrowing"))
&& peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
tok::code_complete)
&& !peekToken().isAtStartOfLine()) {
if (Tok.isContextualKeyword("_borrowing")) {
diagnose(Tok.getLoc(),
diag::borrowing_syntax_change)
.fixItReplace(Tok.getLoc(), "borrowing");
}

Tok.setKind(tok::contextual_keyword);
SourceLoc borrowingLoc = consumeToken();

// If we have `case borrowing x.`, `x(`, `x[`, or `x<` then this looks
// like an attempt to include a subexpression under a `borrowing`
// binding, which isn't yet supported.
if (peekToken().isAny(tok::period, tok::period_prefix, tok::l_paren,
tok::l_square)
|| (peekToken().isAnyOperator() && peekToken().getText().equals("<"))) {

// Diagnose the unsupported production.
diagnose(Tok.getLoc(),
diag::borrowing_subpattern_unsupported);

// Recover by parsing as if it was supported.
return parseMatchingPattern(isExprBasic);
}
Identifier name;
SourceLoc nameLoc = consumeIdentifier(name,
/*diagnoseDollarPrefix*/ false);
auto namedPattern = createBindingFromPattern(nameLoc, name,
VarDecl::Introducer::Borrowing);
auto bindPattern = new (Context) BindingPattern(
borrowingLoc, VarDecl::Introducer::Borrowing, namedPattern);
if ((Tok.isContextualKeyword("_borrowing")
|| Tok.isContextualKeyword("borrowing"))
&& peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
tok::code_complete)
&& !peekToken().isAtStartOfLine()) {
diagnose(Tok.getLoc(),
diag::borrowing_syntax_change)
.fixItReplace(Tok.getLoc(), "let");

Tok.setKind(tok::contextual_keyword);
SourceLoc borrowingLoc = consumeToken();

// If we have `case borrowing x.`, `x(`, `x[`, or `x<` then this looks
// like an attempt to include a subexpression under a `borrowing`
// binding, which isn't yet supported.
if (peekToken().isAny(tok::period, tok::period_prefix, tok::l_paren,
tok::l_square)
|| (peekToken().isAnyOperator() && peekToken().getText().equals("<"))) {

// Diagnose the unsupported production.
diagnose(Tok.getLoc(),
diag::borrowing_subpattern_unsupported);

return makeParserResult(bindPattern);
// Recover by parsing as if it was supported.
return parseMatchingPattern(isExprBasic);
}
Identifier name;
SourceLoc nameLoc = consumeIdentifier(name,
/*diagnoseDollarPrefix*/ false);
auto namedPattern = createBindingFromPattern(nameLoc, name,
VarDecl::Introducer::Borrowing);
auto bindPattern = new (Context) BindingPattern(
borrowingLoc, VarDecl::Introducer::Borrowing, namedPattern);

return makeParserResult(bindPattern);
}

// matching-pattern ::= 'is' type
Expand Down Expand Up @@ -1470,14 +1466,12 @@ Parser::parseMatchingPatternAsBinding(PatternBindingState newState,
}

bool Parser::isOnlyStartOfMatchingPattern() {
if (Context.LangOpts.hasFeature(Feature::BorrowingSwitch)) {
if ((Tok.isContextualKeyword("_borrowing")
|| Tok.isContextualKeyword("borrowing"))
&& peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
tok::code_complete)
&& !peekToken().isAtStartOfLine()) {
return true;
}
if ((Tok.isContextualKeyword("_borrowing")
|| Tok.isContextualKeyword("borrowing"))
&& peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
tok::code_complete)
&& !peekToken().isAtStartOfLine()) {
return true;
}

return Tok.isAny(tok::kw_var, tok::kw_let, tok::kw_is) ||
Expand Down
12 changes: 0 additions & 12 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4170,18 +4170,6 @@ diagnoseMoveOnlyPatternMatchSubject(ASTContext &C,
|| !subjectType->isNoncopyable()) {
return;
}

// A bare reference to, or load from, a move-only binding must be consumed.
subjectExpr = subjectExpr->getSemanticsProvidingExpr();
if (auto load = dyn_cast<LoadExpr>(subjectExpr)) {
subjectExpr = load->getSubExpr()->getSemanticsProvidingExpr();
}
if (!C.LangOpts.hasFeature(Feature::BorrowingSwitch)
&& isa<DeclRefExpr>(subjectExpr)) {
C.Diags.diagnose(subjectExpr->getLoc(),
diag::move_only_pattern_match_not_consumed)
.fixItInsert(subjectExpr->getStartLoc(), "consume ");
}
}

// Perform MiscDiagnostics on Switch Statements.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-experimental-concis
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Macros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "FreestandingMacros")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BorrowingSwitch")
list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BitwiseCopyable")

if("${SWIFT_NATIVE_SWIFT_TOOLS_PATH}" STREQUAL "")
set(swift_bin_dir "${CMAKE_BINARY_DIR}/bin")
Expand Down
7 changes: 3 additions & 4 deletions test/Interpreter/moveonly_linkedlist_2_simple.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// RUN: %target-swift-emit-irgen \
// RUN: -parse-as-library \
// RUN: -enable-builtin-module \
// RUN: -enable-experimental-feature BorrowingSwitch \
// RUN: %s \
// RUN: | \
// RUN: %FileCheck %s --check-prefix=CHECK-IR
// RUN: %target-run-simple-swift(-parse-as-library -enable-builtin-module -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s
// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all) | %FileCheck %s
// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -enable-experimental-feature BorrowingSwitch -Xfrontend -sil-verify-all -Xfrontend -enable-ossa-modules) | %FileCheck %s
// RUN: %target-run-simple-swift(-parse-as-library -enable-builtin-module -Xfrontend -sil-verify-all) | %FileCheck %s
// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -Xfrontend -sil-verify-all) | %FileCheck %s
// RUN: %target-run-simple-swift(-O -parse-as-library -enable-builtin-module -Xfrontend -sil-verify-all -Xfrontend -enable-ossa-modules) | %FileCheck %s

// REQUIRES: executable_test

Expand Down
3 changes: 1 addition & 2 deletions test/Interpreter/moveonly_swiftskell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
// RUN: -module-name Swiftskell \
// RUN: -parse-as-library \
// RUN: %S/../Inputs/Swiftskell.swift -c -o %t/Swiftskell.o \
// RUN: -enable-experimental-feature NonescapableTypes \
// RUN: -enable-experimental-feature BorrowingSwitch
// RUN: -enable-experimental-feature NonescapableTypes

// RUN: %target-build-swift -o %t/a.out %s -I %t %t/Swiftskell.o
// RUN: %target-codesign %t/a.out
Expand Down
1 change: 0 additions & 1 deletion test/ModuleInterface/noncopyable_generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// RUN: %target-swift-frontend -swift-version 5 -enable-library-evolution -emit-module \
// RUN: -enable-experimental-feature SuppressedAssociatedTypes \
// RUN: -enable-experimental-feature NonescapableTypes \
// RUN: -enable-experimental-feature BorrowingSwitch \
// RUN: -o %t/Swiftskell.swiftmodule \
// RUN: -emit-module-interface-path %t/Swiftskell.swiftinterface \
// RUN: %S/../Inputs/Swiftskell.swift
Expand Down
13 changes: 8 additions & 5 deletions test/Parse/pattern_borrow_bindings.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -enable-experimental-feature BorrowingSwitch -typecheck -verify %s
// RUN: %target-swift-frontend -typecheck -verify %s

struct Payload: ~Copyable {
var x: Int
Expand Down Expand Up @@ -38,16 +38,19 @@ func testBorrowingPatterns(bar: borrowing Bar) {
case borrowing (): // parses as `borrowing()` as before
break

case borrowing x:
case borrowing x: // expected-warning{{'borrowing' in pattern matches is deprecated}} {{10-19=let}}
useBorrowBar(x)

case .payload(borrowing x):
case .payload(borrowing x): // expected-warning{{'borrowing' in pattern matches is deprecated}} {{19-28=let}}
useBorrowFoo(x)

case borrowing x.member: // expected-error{{'borrowing' pattern modifier must be directly applied to pattern variable name}} expected-error{{cannot find 'x' in scope}}
case borrowing x.member: // expected-warning{{deprecated}} expected-error{{'borrowing' pattern modifier must be directly applied to pattern variable name}} expected-error{{cannot find 'x' in scope}}
break

case _borrowing x: // expected-warning{{'_borrowing' spelling is deprecated}} {{10-20=borrowing}}
case borrowing x: // expected-warning{{'borrowing' in pattern matches is deprecated}} {{10-19=let}}
useBorrowBar(x)

case _borrowing x: // expected-warning{{'borrowing' in pattern matches is deprecated}} {{10-20=let}}
useBorrowBar(x)

default:
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/borrowing_switch_return_binding_compat.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowingSwitch -verify %s
// RUN: %target-swift-emit-silgen -verify %s
func orElse<T: ~Copyable>(
x: consuming T?,
defaultValue: @autoclosure () throws -> T?
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/borrowing_switch_return_on_all_paths.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowingSwitch -verify %s
// RUN: %target-swift-emit-silgen -verify %s

struct Box<Wrapped: ~Copyable>: ~Copyable {
var wrapped: Wrapped {
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/borrowing_switch_subjects.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowingSwitch %s | %FileCheck %s
// RUN: %target-swift-emit-silgen %s | %FileCheck %s

struct Inner: ~Copyable {}

Expand Down
1 change: 0 additions & 1 deletion test/SILGen/moveonly_consuming_switch.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// RUN: %target-swift-frontend \
// RUN: -emit-silgen \
// RUN: %s \
// RUN: -enable-experimental-feature BorrowingSwitch \
// RUN: | %FileCheck %s

enum MaybeMaybeVoid<Wrapped: ~Copyable>: ~Copyable {
Expand Down
7 changes: 3 additions & 4 deletions test/SILOptimizer/lifetime_dependence_optional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// RUN: -verify \
// RUN: -sil-verify-all \
// RUN: -module-name test \
// RUN: -enable-experimental-feature NonescapableTypes \
// RUN: -enable-experimental-feature BorrowingSwitch
// RUN: -enable-experimental-feature NonescapableTypes

// REQUIRES: asserts
// REQUIRES: swift_in_compiler
Expand Down Expand Up @@ -58,7 +57,7 @@ extension Nillable where Wrapped: ~Copyable {
_ transform: (borrowing Wrapped) throws(E) -> U
) throws(E) -> U? {
switch self {
case .some(borrowing y):
case .some(let y):
return .some(try transform(y))
case .none:
return .none
Expand All @@ -82,7 +81,7 @@ extension Nillable where Wrapped: ~Copyable {
_ transform: (borrowing Wrapped) throws(E) -> U?
) throws(E) -> U? {
switch self {
case .some(borrowing y):
case .some(let y):
return try transform(y)
case .none:
return .none
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-sil %s -O -sil-verify-all -verify -enable-experimental-feature BorrowingSwitch -enable-experimental-feature MoveOnlyPartialReinitialization -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses
// RUN: %target-swift-emit-sil %s -O -sil-verify-all -verify -enable-experimental-feature MoveOnlyPartialReinitialization -enable-experimental-feature NoImplicitCopy -enable-experimental-feature MoveOnlyClasses

//////////////////
// Declarations //
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/moveonly_borrowing_switch.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -verify -enable-experimental-feature BorrowingSwitch %s
// RUN: %target-swift-frontend -emit-sil -verify %s

struct Payload: ~Copyable {
var x: Int
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -verify -enable-experimental-feature BorrowingSwitch %s
// RUN: %target-swift-frontend -emit-sil -verify %s

struct Payload: ~Copyable {
var x: Int
Expand Down Expand Up @@ -31,25 +31,7 @@ func test(borrowing foo: borrowing Foo) {
eat(x)
nibble(x)

// `borrowing` match variables impose the no-implicit-copy constraint
// like `borrowing` parameters do.
case .copyablePayload(borrowing x) // expected-error{{'x' is borrowed and cannot be consumed}}
where hungryCondition(x): // expected-note{{consumed here}}
eat(x) // expected-note{{consumed here}}
nibble(x)

case .copyablePayload(borrowing x) // expected-error{{'x' is borrowed and cannot be consumed}}
where condition(x):
eat(x) // expected-note{{consumed here}}
nibble(x)

// Explicit copies are OK.
case .copyablePayload(borrowing x)
where hungryCondition(copy x):
eat(copy x)
nibble(x)

case .copyablePayload(borrowing x):
case .copyablePayload(let x):
nibble(x)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -enable-experimental-feature BorrowingSwitch -emit-sil -verify %s
// RUN: %target-swift-frontend -emit-sil -verify %s

struct Box<Wrapped: ~Copyable>: ~Copyable {
init(_ element: consuming Wrapped) { }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -verify -enable-experimental-feature BorrowingSwitch -parse-as-library %s
// RUN: %target-swift-frontend -emit-sil -verify -parse-as-library %s

func foo() {
let node = Node()
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/moveonly_borrowing_switch_yield.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -enable-experimental-feature BorrowingSwitch -parse-as-library -O -emit-sil -verify %s
// RUN: %target-swift-frontend -parse-as-library -O -emit-sil -verify %s

extension List {
var peek: Element {
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/moveonly_consuming_switch.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -enable-experimental-feature BorrowingSwitch -verify %s
// RUN: %target-swift-frontend -emit-sil -verify %s

// TODO: Remove this and just use the real `UnsafeMutablePointer` when
// noncopyable type support has been upstreamed.
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/moveonly_consuming_switch_2.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-sil -enable-experimental-feature BorrowingSwitch -verify %s
// RUN: %target-swift-frontend -emit-sil -verify %s

struct Box: ~Copyable {
let ptr: UnsafeMutablePointer<Int>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-sil -enable-experimental-feature BorrowingSwitch -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses %s
// RUN: %target-swift-emit-sil -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses %s

//////////////////
// Declarations //
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-sil -enable-experimental-feature BorrowingSwitch -enable-experimental-feature MoveOnlyPartialReinitialization -sil-verify-all -verify %s
// RUN: %target-swift-emit-sil -enable-experimental-feature MoveOnlyPartialReinitialization -sil-verify-all -verify %s

//////////////////
// Declarations //
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-emit-sil -enable-experimental-feature BorrowingSwitch -sil-verify-all -verify %s
// RUN: %target-swift-emit-sil -sil-verify-all -verify %s

//////////////////
// Declarations //
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// RUN: %target-swift-emit-ir \
// RUN: %s \
// RUN: -enable-builtin-module \
// RUN: -enable-experimental-feature BorrowingSwitch \
// RUN: -sil-verify-all \
// RUN: -verify

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// RUN: %target-swift-emit-sil \
// RUN: %s \
// RUN: -enable-builtin-module \
// RUN: -enable-experimental-feature BorrowingSwitch \
// RUN: -sil-verify-all \
// RUN: -verify

Expand Down