Skip to content

Commit 3fa0886

Browse files
authored
Merge pull request #71677 from meg-gupta/lifetimedepgetter
Support lifetime dependence inference on getters
2 parents 0664c3f + 3ddb524 commit 3fa0886

File tree

6 files changed

+115
-8
lines changed

6 files changed

+115
-8
lines changed

lib/Sema/LifetimeDependence.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,18 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
282282
return llvm::None;
283283
}
284284

285-
if (afd->getKind() == DeclKind::Func && afd->hasImplicitSelfDecl()) {
286-
auto ownership = afd->getImplicitSelfDecl()->getValueOwnership();
285+
if (afd->getKind() != DeclKind::Constructor && afd->hasImplicitSelfDecl()) {
286+
ValueOwnership ownership = ValueOwnership::Default;
287+
if (auto *AD = dyn_cast<AccessorDecl>(afd)) {
288+
if (AD->getAccessorKind() == AccessorKind::Get) {
289+
// We don't support "borrowing/consuming" ownership modifiers on
290+
// getters, by default they are guaranteed for now.
291+
ownership = ValueOwnership::Shared;
292+
}
293+
} else {
294+
ownership = afd->getImplicitSelfDecl()->getValueOwnership();
295+
}
296+
287297
if (ownership == ValueOwnership::Default) {
288298
diags.diagnose(
289299
returnLoc,
@@ -338,10 +348,6 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
338348
llvm::Optional<LifetimeDependenceInfo>
339349
LifetimeDependenceInfo::get(AbstractFunctionDecl *afd, Type resultType,
340350
bool allowIndex) {
341-
if (afd->getKind() != DeclKind::Func &&
342-
afd->getKind() != DeclKind::Constructor) {
343-
return llvm::None;
344-
}
345351
auto *returnTypeRepr = afd->getResultTypeRepr();
346352
if (isa_and_nonnull<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
347353
return LifetimeDependenceInfo::fromTypeRepr(afd, resultType, allowIndex);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,8 +1709,9 @@ Stmt *PreCheckReturnStmtRequest::evaluate(Evaluator &evaluator, ReturnStmt *RS,
17091709

17101710
auto *E = RS->getResult();
17111711

1712-
// In an initializer, the only expression allowed is "nil", which indicates
1713-
// failure from a failable initializer.
1712+
// In an initializer, the only expressions allowed are "nil", which indicates
1713+
// failure from a failable initializer or "self" in the case of ~Escapable
1714+
// initializers with explicit lifetime dependence.
17141715
if (auto *ctor =
17151716
dyn_cast_or_null<ConstructorDecl>(fn->getAbstractFunctionDecl())) {
17161717

test/SIL/buffer_view_prototype.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %target-swift-frontend %s -emit-sil \
2+
// RUN: -disable-experimental-parser-round-trip \
3+
// RUN: -enable-experimental-feature NonescapableTypes \
4+
// RUN: -enable-experimental-feature NoncopyableGenerics \
5+
// RUN: -enable-experimental-lifetime-dependence-inference \
6+
// RUN: -Xllvm -enable-lifetime-dependence-diagnostics
7+
// REQUIRES: noncopyable_generics
8+
9+
public struct BufferView<Element> : ~Escapable {
10+
public typealias Index = Int
11+
public typealias Pointer = UnsafePointer<Element>
12+
public let baseAddress: Pointer
13+
public let count: Int
14+
15+
// TODO: This should be a failable initializer
16+
// Currently optional is Escapable, so we cant yet write it.
17+
public init<Storage>(unsafeBuffer: UnsafeBufferPointer<Element>,
18+
storage: borrowing Storage)
19+
-> _borrow(storage) Self {
20+
let baseAddress = unsafeBuffer.baseAddress!
21+
self = BufferView<Element>(baseAddress: baseAddress,
22+
count: unsafeBuffer.count)
23+
return self
24+
}
25+
// unsafe private API
26+
@_unsafeNonescapableResult
27+
init(baseAddress: Pointer, count: Int) {
28+
precondition(count >= 0, "Count must not be negative")
29+
self.baseAddress = baseAddress
30+
self.count = count
31+
}
32+
subscript(_ index: Index) -> Element? {
33+
if (index < 0 || index >= count) {
34+
return nil
35+
}
36+
return baseAddress[index]
37+
}
38+
}
39+
40+
extension Array {
41+
// var view: BufferView<Element> {
42+
// withUnsafeBufferPointer {
43+
// return BufferView(unsafeBuffer: $0, storage: self)
44+
// }
45+
// }
46+
// TODO: Implementation of getter should not need a temporary
47+
// rdar://123071321
48+
var view: BufferView<Element> {
49+
var _view : BufferView<Element>?
50+
withUnsafeBufferPointer {
51+
_view = BufferView(unsafeBuffer: $0, storage: self)
52+
}
53+
return _view!
54+
}
55+
}
56+
57+
public func array_view_element(a: [Int] , i: Int) -> Int {
58+
a.view[i]!
59+
}
60+

test/SIL/implicit_lifetime_dependence.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,16 @@ struct Wrapper : ~Escapable {
7777
return view
7878
}
7979
}
80+
81+
struct Container : ~Copyable {
82+
var ptr: UnsafeRawBufferPointer
83+
// CHECK: sil hidden @$s28implicit_lifetime_dependence9ContainerV4viewAA10BufferViewVvg : $@convention(method) (@guaranteed Container) -> _scope(0) @owned BufferView {
84+
var view: BufferView {
85+
get {
86+
return BufferView(ptr)
87+
}
88+
set(newView) {
89+
ptr = newView.ptr
90+
}
91+
}
92+
}

test/Serialization/Inputs/def_implicit_lifetime_dependence.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,19 @@ public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
3131
return BufferView(view.ptr)
3232
}
3333

34+
public struct Container : ~Copyable {
35+
var ptr: UnsafeRawBufferPointer
36+
37+
public init(_ ptr: UnsafeRawBufferPointer) {
38+
self.ptr = ptr
39+
}
40+
41+
public var view: BufferView {
42+
get {
43+
return BufferView(ptr)
44+
}
45+
set(newView) {
46+
ptr = newView.ptr
47+
}
48+
}
49+
}

test/Serialization/implicit_lifetime_dependence.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ func unsafetest(_ ptr: UnsafeRawBufferPointer) {
4646
use(view3)
4747
}
4848

49+
func testGetter() {
50+
let capacity = 4
51+
let a = Array(0..<capacity)
52+
a.withUnsafeBytes {
53+
let c = Container($0)
54+
let view = c.view
55+
use(view)
56+
}
57+
}
58+
4959
// CHECK: sil @$s32def_implicit_lifetime_dependence6deriveyAA10BufferViewVADYlsF : $@convention(thin) (@guaranteed BufferView) -> _scope(1) @owned BufferView
5060

5161
// CHECK: sil @$s32def_implicit_lifetime_dependence16consumeAndCreateyAA10BufferViewVADnYliF : $@convention(thin) (@owned BufferView) -> _inherit(1) @owned BufferView
@@ -54,3 +64,4 @@ func unsafetest(_ ptr: UnsafeRawBufferPointer) {
5464

5565
// CHECK: sil @$s32def_implicit_lifetime_dependence10BufferViewVyA2ChYlscfC : $@convention(method) (@guaranteed BufferView, @thin BufferView.Type) -> _scope(1) @owned BufferView
5666

67+
// CHECK: sil @$s32def_implicit_lifetime_dependence9ContainerV4viewAA10BufferViewVvg : $@convention(method) (@guaranteed Container) -> _scope(0) @owned BufferView

0 commit comments

Comments
 (0)