Skip to content

Commit 76c9585

Browse files
authored
Merge pull request #71265 from meg-gupta/initlifetimedepinference
Enable lifetime dependence inference on initializers of ~Escapable types
2 parents cc25000 + 843d003 commit 76c9585

File tree

6 files changed

+70
-21
lines changed

6 files changed

+70
-21
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,9 @@ namespace swift {
556556
/// Enable experimental associated type inference improvements.
557557
bool EnableExperimentalAssociatedTypeInference = false;
558558

559+
/// Enable implicit lifetime dependence for ~Escapable return types.
560+
bool EnableExperimentalLifetimeDependenceInference = false;
561+
559562
/// Enables dumping type witness systems from associated type inference.
560563
bool DumpTypeWitnessSystems = false;
561564

include/swift/Option/FrontendOptions.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,14 @@ def disable_experimental_associated_type_inference :
660660
Flag<["-"], "disable-experimental-associated-type-inference">,
661661
HelpText<"Disable experimental associated type inference improvements">;
662662

663+
def enable_experimental_lifetime_dependence_inference :
664+
Flag<["-"], "enable-experimental-lifetime-dependence-inference">,
665+
HelpText<"Enable experimental lifetime dependence inference">;
666+
667+
def disable_experimental_lifetime_dependence_inference :
668+
Flag<["-"], "disable-experimental-lifetime-dependence-inference">,
669+
HelpText<"Disable experimental lifetime dependence inference">;
670+
663671
def disable_availability_checking : Flag<["-"],
664672
"disable-availability-checking">,
665673
HelpText<"Disable checking for potentially unavailable APIs">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
13461346
if (Args.hasArg(OPT_disable_experimental_associated_type_inference))
13471347
Opts.EnableExperimentalAssociatedTypeInference = false;
13481348

1349+
if (Args.hasArg(OPT_enable_experimental_lifetime_dependence_inference))
1350+
Opts.EnableExperimentalLifetimeDependenceInference = true;
1351+
if (Args.hasArg(OPT_disable_experimental_lifetime_dependence_inference))
1352+
Opts.EnableExperimentalLifetimeDependenceInference = false;
1353+
13491354
Opts.DumpTypeWitnessSystems = Args.hasArg(OPT_dump_type_witness_systems);
13501355

13511356
for (auto &block: FrontendOpts.BlocklistConfigFilePaths)

lib/Sema/LifetimeDependence.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,15 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
219219
return llvm::None;
220220
}
221221

222+
// Perform lifetime dependence inference under a flag only. Currently all
223+
// stdlib types can appear is ~Escapable and ~Copyable.
224+
if (!ctx.LangOpts.EnableExperimentalLifetimeDependenceInference) {
225+
return llvm::None;
226+
}
227+
222228
auto &diags = ctx.Diags;
223229
auto returnTypeRepr = afd->getResultTypeRepr();
224-
auto returnLoc = returnTypeRepr->getLoc();
230+
auto returnLoc = returnTypeRepr ? returnTypeRepr->getLoc() : afd->getLoc();
225231
Type returnTyInContext = afd->mapTypeIntoContext(resultType);
226232

227233
if (returnTyInContext->isEscapable()) {
@@ -231,7 +237,7 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
231237
return llvm::None;
232238
}
233239

234-
if (afd->hasImplicitSelfDecl()) {
240+
if (afd->getKind() == DeclKind::Func && afd->hasImplicitSelfDecl()) {
235241
auto ownership = afd->getImplicitSelfDecl()->getValueOwnership();
236242
if (ownership == ValueOwnership::Default) {
237243
diags.diagnose(
@@ -285,13 +291,14 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
285291
llvm::Optional<LifetimeDependenceInfo>
286292
LifetimeDependenceInfo::get(AbstractFunctionDecl *afd, Type resultType,
287293
bool allowIndex) {
288-
auto *returnTypeRepr = afd->getResultTypeRepr();
289-
if (!returnTypeRepr) {
294+
if (afd->getKind() != DeclKind::Func &&
295+
afd->getKind() != DeclKind::Constructor) {
290296
return llvm::None;
291297
}
292-
if (!isa<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
293-
return LifetimeDependenceInfo::infer(afd, resultType);
298+
auto *returnTypeRepr = afd->getResultTypeRepr();
299+
if (isa_and_nonnull<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
300+
return LifetimeDependenceInfo::fromTypeRepr(afd, resultType, allowIndex);
294301
}
295-
return LifetimeDependenceInfo::fromTypeRepr(afd, resultType, allowIndex);
302+
return LifetimeDependenceInfo::infer(afd, resultType);
296303
}
297304
} // namespace swift

test/SIL/explicit_lifetime_dependence_specifiers.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1-
// RUN: %target-swift-frontend %s -emit-sil -enable-builtin-module \
2-
// RUN: -Xllvm -disable-lifetime-dependence-diagnostics \
3-
// RUN: -enable-experimental-feature NonescapableTypes \
4-
// RUN: -disable-experimental-parser-round-trip \
5-
// RUN: -enable-experimental-feature NoncopyableGenerics \
6-
// RUN: | %FileCheck %s
7-
1+
// RUN: %target-swift-frontend %s \
2+
// RUN: -emit-sil \
3+
// RUN: -enable-builtin-module \
4+
// RUN: -Xllvm -disable-lifetime-dependence-diagnostics \
5+
// RUN: -enable-experimental-feature NonescapableTypes \
6+
// RUN: -disable-experimental-parser-round-trip \
7+
// RUN: -enable-experimental-feature NoncopyableGenerics \
8+
// RUN: -enable-experimental-lifetime-dependence-inference | %FileCheck %s
89
// REQUIRES: asserts
910

1011
import Builtin
1112

1213
struct BufferView : ~Escapable {
1314
let ptr: UnsafeRawBufferPointer
15+
@_unsafeNonescapableResult
1416
init(_ ptr: UnsafeRawBufferPointer) {
1517
self.ptr = ptr
1618
}
1719
}
1820

1921
struct MutableBufferView : ~Escapable, ~Copyable {
2022
let ptr: UnsafeMutableRawBufferPointer
23+
@_unsafeNonescapableResult
2124
init(_ ptr: UnsafeMutableRawBufferPointer) {
2225
self.ptr = ptr
2326
}
2427
}
2528

29+
/*
30+
// rdar://121983770
2631
func testBasic() {
2732
let capacity = 4
2833
let a = Array(0..<capacity)
@@ -33,6 +38,7 @@ func testBasic() {
3338
use(newView)
3439
}
3540
}
41+
*/
3642

3743
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers6deriveyAA10BufferViewVADF : $@convention(thin) (@guaranteed BufferView) -> _borrow(1) @owned BufferView {
3844
func derive(_ x: borrowing BufferView) -> _borrow(x) BufferView {
@@ -64,6 +70,9 @@ func use(_ x: borrowing BufferView) {}
6470

6571
struct Wrapper : ~Escapable {
6672
let view: BufferView
73+
init(_ view: consuming BufferView) {
74+
self.view = view
75+
}
6776
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers7WrapperV8getView1AA10BufferViewVyF : $@convention(method) (@guaranteed Wrapper) -> _borrow(0) @owned BufferView {
6877
borrowing func getView1() -> _borrow(self) BufferView {
6978
return view

test/SIL/implicit_lifetime_dependence.swift

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
1-
// RUN: %target-swift-frontend %s -emit-sil -enable-builtin-module \
2-
// RUN: -Xllvm -disable-lifetime-dependence-diagnostics \
3-
// RUN: -enable-experimental-feature NonescapableTypes \
4-
// RUN: -disable-experimental-parser-round-trip \
5-
// RUN: -enable-experimental-feature NoncopyableGenerics \
6-
// RUN: | %FileCheck %s
7-
1+
// RUN: %target-swift-frontend %s \
2+
// RUN: -emit-sil \
3+
// RUN: -enable-builtin-module \
4+
// RUN: -Xllvm -disable-lifetime-dependence-diagnostics \
5+
// RUN: -enable-experimental-feature NonescapableTypes \
6+
// RUN: -disable-experimental-parser-round-trip \
7+
// RUN: -enable-experimental-feature NoncopyableGenerics \
8+
// RUN: -enable-experimental-lifetime-dependence-inference | %FileCheck %s
89
// REQUIRES: asserts
910

1011
import Builtin
1112

1213
struct BufferView : ~Escapable {
1314
let ptr: UnsafeRawBufferPointer
15+
@_unsafeNonescapableResult
1416
init(_ ptr: UnsafeRawBufferPointer) {
1517
self.ptr = ptr
1618
}
19+
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2ChcfC : $@convention(method) (@guaranteed BufferView, @thin BufferView.Type) -> _borrow(1) @owned BufferView {
20+
init(_ otherBV: borrowing BufferView) {
21+
self.ptr = otherBV.ptr
22+
}
23+
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2CcfC : $@convention(method) (@owned BufferView, @thin BufferView.Type) -> _inherit(1) @owned BufferView {
24+
init(_ otherBV: consuming BufferView) {
25+
self.ptr = otherBV.ptr
26+
}
1727
}
1828

1929
struct MutableBufferView : ~Escapable, ~Copyable {
2030
let ptr: UnsafeMutableRawBufferPointer
31+
@_unsafeNonescapableResult
2132
init(_ ptr: UnsafeMutableRawBufferPointer) {
2233
self.ptr = ptr
2334
}
2435
}
2536

37+
/*
38+
// rdar://121983770
2639
func testBasic() {
2740
let capacity = 4
2841
let a = Array(0..<capacity)
@@ -33,6 +46,7 @@ func testBasic() {
3346
use(newView)
3447
}
3548
}
49+
*/
3650

3751
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence6deriveyAA10BufferViewVADF : $@convention(thin) (@guaranteed BufferView) -> _borrow(1) @owned BufferView {
3852
func derive(_ x: borrowing BufferView) -> BufferView {
@@ -48,6 +62,9 @@ func use(_ x: borrowing BufferView) {}
4862

4963
struct Wrapper : ~Escapable {
5064
let view: BufferView
65+
init(_ view: consuming BufferView) {
66+
self.view = view
67+
}
5168
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperV8getView1AA10BufferViewVyF : $@convention(method) (@guaranteed Wrapper) -> _borrow(0) @owned BufferView {
5269
borrowing func getView1() -> BufferView {
5370
return view

0 commit comments

Comments
 (0)