Update tests for strict @lifetime type checking

This commit is contained in:
Andrew Trick
2025-03-15 09:28:18 -07:00
parent 88a242f175
commit 64a48d08e1
53 changed files with 231 additions and 139 deletions

View File

@@ -219,13 +219,13 @@ struct OpTest {
struct E {} struct E {}
struct NE : ~Escapable {} struct NE : ~Escapable {}
@lifetime(ne) func derive(_ ne: NE) -> NE { ne } @lifetime(copy ne) func derive(_ ne: NE) -> NE { ne }
@lifetime(borrow ne1, ne2) func derive(_ ne1: NE, _ ne2: NE) -> NE { @lifetime(borrow ne1, copy ne2) func derive(_ ne1: NE, _ ne2: NE) -> NE {
if (Int.random(in: 1..<100) < 50) { return ne1 } if (Int.random(in: 1..<100) < 50) { return ne1 }
return ne2 return ne2
} }
@lifetime(borrow borrow) func testNameConflict(_ borrow: E) -> NE { NE() } @lifetime(borrow borrow) func testNameConflict(_ borrow: E) -> NE { NE() }
@lifetime(result: source) func testTarget(_ result: inout NE, _ source: consuming NE) { result = source } @lifetime(result: copy source) func testTarget(_ result: inout NE, _ source: consuming NE) { result = source }
actor MyActor { actor MyActor {
nonisolated let constFlag: Bool = false nonisolated let constFlag: Bool = false

View File

@@ -1,6 +1,9 @@
// RUN: %target-typecheck-verify-swift \ // RUN: %target-typecheck-verify-swift \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -debug-diagnostic-names -target arm64-apple-macos14.4 // RUN: -debug-diagnostic-names -target arm64-apple-macos14.4
// REQUIRES: swift_feature_LifetimeDependence
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchOS || OS=xros // REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchOS || OS=xros
protocol P {} protocol P {}

View File

@@ -1,4 +1,8 @@
// RUN: %target-swift-frontend -typecheck -verify %s // RUN: %target-swift-frontend \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -typecheck -verify %s
// REQUIRES: swift_feature_LifetimeDependence
struct C_C1<T: ~Copyable>: ~Copyable {} struct C_C1<T: ~Copyable>: ~Copyable {}
extension C_C1: Copyable where T: Copyable {} extension C_C1: Copyable where T: Copyable {}

View File

@@ -1,6 +1,8 @@
// RUN: %target-typecheck-verify-swift \ // RUN: %target-typecheck-verify-swift \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -enable-experimental-feature SuppressedAssociatedTypes // RUN: -enable-experimental-feature SuppressedAssociatedTypes
// REQUIRES: swift_feature_LifetimeDependence
// REQUIRES: swift_feature_SuppressedAssociatedTypes // REQUIRES: swift_feature_SuppressedAssociatedTypes
protocol P {} protocol P {}

View File

@@ -1,7 +1,9 @@
// RUN: %target-swift-frontend \ // RUN: %target-swift-frontend \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -verify -typecheck %s -debug-generic-signatures \ // RUN: -verify -typecheck %s -debug-generic-signatures \
// RUN: -debug-inverse-requirements 2>&1 | %FileCheck %s --implicit-check-not "error:" // RUN: -debug-inverse-requirements 2>&1 | %FileCheck %s --implicit-check-not "error:"
// REQUIRES: swift_feature_LifetimeDependence
// CHECK-LABEL: .Outer@ // CHECK-LABEL: .Outer@
// CHECK: Generic signature: <A where A : Escapable> // CHECK: Generic signature: <A where A : Escapable>

View File

@@ -249,6 +249,7 @@ struct BuggerView<T: ~Copyable>: ~Escapable, Copyable {}
struct MutableBuggerView<T: ~Copyable>: ~Copyable, ~Escapable {} struct MutableBuggerView<T: ~Copyable>: ~Copyable, ~Escapable {}
@lifetime(mutRef: copy mutRef)
func checkNominals(_ mutRef: inout MutableBuggerView<NC>, func checkNominals(_ mutRef: inout MutableBuggerView<NC>,
_ ref: BuggerView<NC>, _ ref: BuggerView<NC>,
_ intMutRef: borrowing MutableBuggerView<Int>, _ intMutRef: borrowing MutableBuggerView<Int>,

View File

@@ -14,7 +14,7 @@ import CountedByNoEscapeClang
// CHECK: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: MutableSpan<Int{{.*}}>) // CHECK: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: MutableSpan<Int{{.*}}>)
// CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: MutableSpan<Int{{.*}}>) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: MutableSpan<Int{{.*}}>)
// CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: MutableSpan<Int{{.*}}>) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: MutableSpan<Int{{.*}}>)
// CHECK-NEXT: @lifetime(p) // CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: MutableSpan<Int32>) -> MutableSpan<Int32> // CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: MutableSpan<Int32>) -> MutableSpan<Int32>
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableBufferPointer<Int{{.*}}> // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableBufferPointer<Int{{.*}}>
// CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: MutableSpan<Int{{.*}}>, _ p2: MutableSpan<Int{{.*}}>) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: MutableSpan<Int{{.*}}>, _ p2: MutableSpan<Int{{.*}}>)

View File

@@ -21,7 +21,7 @@ module Test {
struct SWIFT_NONESCAPABLE View { struct SWIFT_NONESCAPABLE View {
__attribute__((swift_attr("@lifetime(immortal)"))) __attribute__((swift_attr("@lifetime(immortal)")))
View() : member(nullptr) {} View() : member(nullptr) {}
__attribute__((swift_attr("@lifetime(p)"))) __attribute__((swift_attr("@lifetime(copy p)")))
View(const int *p [[clang::lifetimebound]]) : member(p) {} View(const int *p [[clang::lifetimebound]]) : member(p) {}
View(const View&) = default; View(const View&) = default;
private: private:

View File

@@ -35,11 +35,11 @@ import CxxStdlib
// CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>) // CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>)
// CHECK-NEXT: } // CHECK-NEXT: }
// CHECK: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span<CInt>) // CHECK: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span<CInt>)
// CHECK-NEXT: @lifetime(s) // CHECK-NEXT: @lifetime(copy s)
// CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span<CInt>) -> Span<CInt> // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span<CInt>) -> Span<CInt>
// CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @lifetime(borrow v)
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> Span<CInt> // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> Span<CInt>
// CHECK-NEXT: @lifetime(p) // CHECK-NEXT: @lifetime(copy p)
// CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper1(_ p: Span<Int32>) -> Span<CInt> // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper1(_ p: Span<Int32>) -> Span<CInt>
// CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @lifetime(borrow v)
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func mixedFuncWithSafeWrapper2(_ v: borrowing VecOfInt, _ len: Int32) -> Span<Int32> // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func mixedFuncWithSafeWrapper2(_ v: borrowing VecOfInt, _ len: Int32) -> Span<Int32>

View File

@@ -28,7 +28,7 @@ func lifetimeDependentBorrow(_ p: borrowing UnsafePointer<CInt>, _ len1: CInt, _
// CHECK-NEXT: func nonEscaping(_ len: CInt) -> UnsafeBufferPointer<CInt> { // CHECK-NEXT: func nonEscaping(_ len: CInt) -> UnsafeBufferPointer<CInt> {
// CHECK-NEXT: return unsafe UnsafeBufferPointer<CInt> (start: nonEscaping(len), count: Int(len)) // CHECK-NEXT: return unsafe UnsafeBufferPointer<CInt> (start: nonEscaping(len), count: Int(len))
// CHECK: @_alwaysEmitIntoClient @lifetime(p) // CHECK: @_alwaysEmitIntoClient @lifetime(copy p)
// CHECK-NEXT: func lifetimeDependentCopy(_ p: Span<CInt>, _ len2: CInt) -> Span<CInt> { // CHECK-NEXT: func lifetimeDependentCopy(_ p: Span<CInt>, _ len2: CInt) -> Span<CInt> {
// CHECK-NEXT: return unsafe Span<CInt> (_unsafeStart: p.withUnsafeBufferPointer { _pPtr in // CHECK-NEXT: return unsafe Span<CInt> (_unsafeStart: p.withUnsafeBufferPointer { _pPtr in
// CHECK-NEXT: return unsafe lifetimeDependentCopy(_pPtr.baseAddress!, CInt(exactly: p.count)!, len2) // CHECK-NEXT: return unsafe lifetimeDependentCopy(_pPtr.baseAddress!, CInt(exactly: p.count)!, len2)

View File

@@ -32,7 +32,7 @@ struct X {
func myFunc5() -> SpanOfInt {} func myFunc5() -> SpanOfInt {}
} }
// CHECK: @_alwaysEmitIntoClient @lifetime(span) // CHECK: @_alwaysEmitIntoClient @lifetime(copy span)
// CHECK-NEXT: func myFunc(_ span: Span<CInt>) -> Span<CInt> { // CHECK-NEXT: func myFunc(_ span: Span<CInt>) -> Span<CInt> {
// CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc(SpanOfInt(span)))) // CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc(SpanOfInt(span))))
// CHECK-NEXT: } // CHECK-NEXT: }
@@ -42,12 +42,12 @@ struct X {
// CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc2(vec))) // CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc2(vec)))
// CHECK-NEXT: } // CHECK-NEXT: }
// CHECK: @_alwaysEmitIntoClient @lifetime(span1, span2) // CHECK: @_alwaysEmitIntoClient @lifetime(copy span1, copy span2)
// CHECK-NEXT: func myFunc3(_ span1: Span<CInt>, _ span2: Span<CInt>) -> Span<CInt> { // CHECK-NEXT: func myFunc3(_ span1: Span<CInt>, _ span2: Span<CInt>) -> Span<CInt> {
// CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc3(SpanOfInt(span1), SpanOfInt(span2)))) // CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc3(SpanOfInt(span1), SpanOfInt(span2))))
// CHECK-NEXT: } // CHECK-NEXT: }
// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, span) // CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, copy span)
// CHECK-NEXT: func myFunc4(_ vec: borrowing VecOfInt, _ span: Span<CInt>) -> Span<CInt> { // CHECK-NEXT: func myFunc4(_ vec: borrowing VecOfInt, _ span: Span<CInt>) -> Span<CInt> {
// CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc4(vec, SpanOfInt(span)))) // CHECK-NEXT: return unsafe _unsafeRemoveLifetime(Span(_unsafeCxxSpan: myFunc4(vec, SpanOfInt(span))))
// CHECK-NEXT: } // CHECK-NEXT: }

View File

@@ -10,7 +10,7 @@ internal func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escap
@_unsafeNonescapableResult @_unsafeNonescapableResult
@_alwaysEmitIntoClient @_alwaysEmitIntoClient
@_transparent @_transparent
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>( internal func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
_ dependent: consuming T, copying source: borrowing U) -> T { _ dependent: consuming T, copying source: borrowing U) -> T {
dependent dependent
@@ -43,7 +43,7 @@ public struct BufferView : ~Escapable {
self = _overrideLifetime(bv, borrowing: a) self = _overrideLifetime(bv, borrowing: a)
} }
@inlinable @inlinable
@lifetime(a) @lifetime(copy a)
internal init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView) { internal init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView) {
let bv = BufferView(ptr, a._count) let bv = BufferView(ptr, a._count)
self = _overrideLifetime(bv, copying: a) self = _overrideLifetime(bv, copying: a)
@@ -51,7 +51,7 @@ public struct BufferView : ~Escapable {
} }
@inlinable @inlinable
@lifetime(x) @lifetime(copy x)
public func derive(_ x: consuming BufferView) -> BufferView { public func derive(_ x: consuming BufferView) -> BufferView {
let pointer = x._ptr let pointer = x._ptr
let bv = BufferView(pointer, x._count) let bv = BufferView(pointer, x._count)
@@ -62,7 +62,7 @@ public func derive(_ x: consuming BufferView) -> BufferView {
public func use(_ x: consuming BufferView) {} public func use(_ x: consuming BufferView) {}
@inlinable @inlinable
@lifetime(view) @lifetime(copy view)
public func consumeAndCreate(_ view: consuming BufferView) -> BufferView { public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
let pointer = view._ptr let pointer = view._ptr
let bv = BufferView(pointer, view._count) let bv = BufferView(pointer, view._count)
@@ -70,7 +70,7 @@ public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
} }
@inlinable @inlinable
@lifetime(this, that) @lifetime(copy this, copy that)
public func deriveThisOrThat(_ this: consuming BufferView, _ that: consuming BufferView) -> BufferView { public func deriveThisOrThat(_ this: consuming BufferView, _ that: consuming BufferView) -> BufferView {
if (Int.random(in: 1..<100) == 0) { if (Int.random(in: 1..<100) == 0) {
return BufferView(this._ptr, this._count) return BufferView(this._ptr, this._count)

View File

@@ -24,16 +24,16 @@
import lifetime_dependence import lifetime_dependence
// CHECK: @lifetime(borrow a) // CHECK: @lifetime(borrow a)
// CHECK-NEXT: @inlinable internal init(_ ptr: Swift.UnsafeRawBufferPointer, _ a: borrowing Swift.Array<Swift.Int>) { // CHECK-NEXT: @inlinable internal init(_ ptr: Swift.UnsafeRawBufferPointer, _ a: borrowing Swift.Array<Swift.Int>) {
// CHECK: @lifetime(a) // CHECK: @lifetime(copy a)
// CHECK-NEXT: @inlinable internal init(_ ptr: Swift.UnsafeRawBufferPointer, _ a: consuming lifetime_dependence.AnotherView) { // CHECK-NEXT: @inlinable internal init(_ ptr: Swift.UnsafeRawBufferPointer, _ a: consuming lifetime_dependence.AnotherView) {
// CHECK: @lifetime(x) // CHECK: @lifetime(copy x)
// CHECK-NEXT: @inlinable public func derive(_ x: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView { // CHECK-NEXT: @inlinable public func derive(_ x: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView {
// CHECK: @lifetime(view) // CHECK: @lifetime(copy view)
// CHECK-NEXT: @inlinable public func consumeAndCreate(_ view: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView { // CHECK-NEXT: @inlinable public func consumeAndCreate(_ view: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView {
// CHECK: @lifetime(this, that) // CHECK: @lifetime(copy this, copy that)
// CHECK-NEXT: @inlinable public func deriveThisOrThat(_ this: consuming lifetime_dependence.BufferView, _ that: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView { // CHECK-NEXT: @inlinable public func deriveThisOrThat(_ this: consuming lifetime_dependence.BufferView, _ that: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView {
// Check that an implicitly dependent variable accessor is guarded by LifetimeDependence. // Check that an implicitly dependent variable accessor is guarded by LifetimeDependence.

View File

@@ -50,19 +50,19 @@ public enum Y<T: ~Escapable>: ~Escapable {
extension Y: Escapable where T: Escapable { } extension Y: Escapable where T: Escapable { }
// CHECK: #if compiler(>=5.3) && $NonescapableTypes // CHECK: #if compiler(>=5.3) && $NonescapableTypes
// CHECK: @lifetime(y) // CHECK: @lifetime(copy y)
// CHECK: public func derive<T>(_ y: Test.Y<T>) -> Test.Y<T> where T : ~Escapable // CHECK: public func derive<T>(_ y: Test.Y<T>) -> Test.Y<T> where T : ~Escapable
// CHECK: #endif // CHECK: #endif
@lifetime(y) @lifetime(copy y)
public func derive<T : ~Escapable>(_ y: Y<T>) -> Y<T> { public func derive<T : ~Escapable>(_ y: Y<T>) -> Y<T> {
y y
} }
// CHECK: #if compiler(>=5.3) && $NonescapableTypes // CHECK: #if compiler(>=5.3) && $NonescapableTypes
// CHECK: @lifetime(x) // CHECK: @lifetime(copy x)
// CHECK: public func derive<T>(_ x: Test.X<T>) -> Test.X<T> where T : ~Escapable // CHECK: public func derive<T>(_ x: Test.X<T>) -> Test.X<T> where T : ~Escapable
// CHECK: #endif // CHECK: #endif
@lifetime(x) @lifetime(copy x)
public func derive<T : ~Escapable>(_ x: X<T>) -> X<T> { public func derive<T : ~Escapable>(_ x: X<T>) -> X<T> {
x x
} }

View File

@@ -1,4 +1,7 @@
// RUN: %target-typecheck-verify-swift // RUN: %target-typecheck-verify-swift \
// RUN: -enable-experimental-feature LifetimeDependence
// REQUIRES: swift_feature_LifetimeDependence
struct S: ~Escapable {} struct S: ~Escapable {}

View File

@@ -6,12 +6,12 @@ struct E {}
struct NE : ~Escapable {} struct NE : ~Escapable {}
@lifetime(ne) @lifetime(copy ne)
func derive(_ ne: NE) -> NE { func derive(_ ne: NE) -> NE {
ne ne
} }
@lifetime(borrow ne1, ne2) @lifetime(borrow ne1, copy ne2)
func derive(_ ne1: NE, _ ne2: NE) -> NE { func derive(_ ne1: NE, _ ne2: NE) -> NE {
if (Int.random(in: 1..<100) < 50) { if (Int.random(in: 1..<100) < 50) {
return ne1 return ne1
@@ -19,13 +19,13 @@ func derive(_ ne1: NE, _ ne2: NE) -> NE {
return ne2 return ne2
} }
@lifetime // expected-error{{expected '(' after lifetime dependence specifier}} @lifetime // expected-error{{expected '(' after lifetime dependence specifier}}
func testMissingLParenError(_ ne: NE) -> NE { func testMissingLParenError(_ ne: NE) -> NE { // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@lifetime(borrow ne)' or '@lifetime(copy ne)'}}
ne ne
} }
@lifetime() // expected-error{{expected identifier, index or self in lifetime dependence specifier}} @lifetime() // expected-error{{expected identifier, index or self in lifetime dependence specifier}}
func testMissingDependence(_ ne: NE) -> NE { func testMissingDependence(_ ne: NE) -> NE { // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@lifetime(borrow ne)' or '@lifetime(copy ne)'}}
ne ne
} }

View File

@@ -1,9 +1,11 @@
// RUN: %empty-directory(%t) // RUN: %empty-directory(%t)
// RUN: %target-build-swift -target %target-swift-5.1-abi-triple -parse-stdlib %s -module-name main -o %t/a.out // RUN: %target-build-swift -target %target-swift-5.1-abi-triple -parse-stdlib %s -module-name main -o %t/a.out \
// RUN: -enable-experimental-feature LifetimeDependence
// RUN: %target-codesign %t/a.out // RUN: %target-codesign %t/a.out
// RUN: %target-run %t/a.out // RUN: %target-run %t/a.out
// REQUIRES: executable_test // REQUIRES: executable_test
// REQUIRES: concurrency // REQUIRES: concurrency
// REQUIRES: swift_feature_LifetimeDependence
// UNSUPPORTED: use_os_stdlib // UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime // UNSUPPORTED: back_deployment_runtime

View File

@@ -29,6 +29,7 @@ struct NCG<T> : ~Copyable {
// CHECK-NEXT: var t: T // CHECK-NEXT: var t: T
struct NEG<T : ~Escapable> : ~Escapable { struct NEG<T : ~Escapable> : ~Escapable {
var t: T var t: T
@lifetime(copy t)
init(_ t: consuming T) { init(_ t: consuming T) {
self.t = t self.t = t
} }

View File

@@ -21,7 +21,7 @@ internal func _overrideLifetime<
} }
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(
@@ -56,12 +56,12 @@ struct BufferView : ~Escapable {
self.ptr = ptr self.ptr = ptr
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers10BufferViewVyACSW_AA7WrapperVtcfC : $@convention(method) (UnsafeRawBufferPointer, @owned Wrapper, @thin BufferView.Type) -> @lifetime(copy 1) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers10BufferViewVyACSW_AA7WrapperVtcfC : $@convention(method) (UnsafeRawBufferPointer, @owned Wrapper, @thin BufferView.Type) -> @lifetime(copy 1) @owned BufferView {
@lifetime(a) @lifetime(copy a)
init(_ ptr: UnsafeRawBufferPointer, _ a: consuming Wrapper) { init(_ ptr: UnsafeRawBufferPointer, _ a: consuming Wrapper) {
self.ptr = ptr self.ptr = ptr
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers10BufferViewVyACSW_AA7WrapperVSaySiGhtcfC : $@convention(method) (UnsafeRawBufferPointer, @owned Wrapper, @guaranteed Array<Int>, @thin BufferView.Type) -> @lifetime(copy 1, borrow 2) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers10BufferViewVyACSW_AA7WrapperVSaySiGhtcfC : $@convention(method) (UnsafeRawBufferPointer, @owned Wrapper, @guaranteed Array<Int>, @thin BufferView.Type) -> @lifetime(copy 1, borrow 2) @owned BufferView {
@lifetime(a, borrow b) @lifetime(copy a, borrow b)
init(_ ptr: UnsafeRawBufferPointer, _ a: consuming Wrapper, _ b: borrowing Array<Int>) { init(_ ptr: UnsafeRawBufferPointer, _ a: consuming Wrapper, _ b: borrowing Array<Int>) {
self.ptr = ptr self.ptr = ptr
} }
@@ -93,14 +93,14 @@ func derive(_ x: borrowing BufferView) -> BufferView {
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers16consumeAndCreateyAA10BufferViewVADnF : $@convention(thin) (@owned BufferView) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers16consumeAndCreateyAA10BufferViewVADnF : $@convention(thin) (@owned BufferView) -> @lifetime(copy 0) @owned BufferView {
@lifetime(x) @lifetime(copy x)
func consumeAndCreate(_ x: consuming BufferView) -> BufferView { func consumeAndCreate(_ x: consuming BufferView) -> BufferView {
let bv = BufferView(independent: x.ptr) let bv = BufferView(independent: x.ptr)
return _overrideLifetime(bv, copying: x) return _overrideLifetime(bv, copying: x)
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers17deriveThisOrThat1yAA10BufferViewVAD_ADtF : $@convention(thin) (@guaranteed BufferView, @guaranteed BufferView) -> @lifetime(copy 1, borrow 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers17deriveThisOrThat1yAA10BufferViewVAD_ADtF : $@convention(thin) (@guaranteed BufferView, @guaranteed BufferView) -> @lifetime(copy 1, borrow 0) @owned BufferView {
@lifetime(borrow this, that) @lifetime(borrow this, copy that)
func deriveThisOrThat1(_ this: borrowing BufferView, _ that: borrowing BufferView) -> BufferView { func deriveThisOrThat1(_ this: borrowing BufferView, _ that: borrowing BufferView) -> BufferView {
if (Int.random(in: 1..<100) == 0) { if (Int.random(in: 1..<100) == 0) {
return BufferView(independent: this.ptr) return BufferView(independent: this.ptr)
@@ -109,7 +109,7 @@ func deriveThisOrThat1(_ this: borrowing BufferView, _ that: borrowing BufferVie
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers17deriveThisOrThat2yAA10BufferViewVAD_ADntF : $@convention(thin) (@guaranteed BufferView, @owned BufferView) -> @lifetime(copy 1, borrow 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers17deriveThisOrThat2yAA10BufferViewVAD_ADntF : $@convention(thin) (@guaranteed BufferView, @owned BufferView) -> @lifetime(copy 1, borrow 0) @owned BufferView {
@lifetime(borrow this, that) @lifetime(borrow this, copy that)
func deriveThisOrThat2(_ this: borrowing BufferView, _ that: consuming BufferView) -> BufferView { func deriveThisOrThat2(_ this: borrowing BufferView, _ that: consuming BufferView) -> BufferView {
if (Int.random(in: 1..<100) == 0) { if (Int.random(in: 1..<100) == 0) {
return BufferView(independent: this.ptr) return BufferView(independent: this.ptr)
@@ -122,6 +122,7 @@ func use(_ x: borrowing BufferView) {}
struct Wrapper : ~Escapable { struct Wrapper : ~Escapable {
let view: BufferView let view: BufferView
@lifetime(copy view)
init(_ view: consuming BufferView) { init(_ view: consuming BufferView) {
self.view = view self.view = view
} }
@@ -132,7 +133,7 @@ struct Wrapper : ~Escapable {
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers7WrapperV8getView2AA10BufferViewVyF : $@convention(method) (@owned Wrapper) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers7WrapperV8getView2AA10BufferViewVyF : $@convention(method) (@owned Wrapper) -> @lifetime(copy 0) @owned BufferView {
@lifetime(self) @lifetime(copy self)
consuming func getView2() -> BufferView { consuming func getView2() -> BufferView {
return view return view
} }
@@ -147,7 +148,7 @@ struct Container : ~Escapable {
} }
// CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers16getConsumingViewyAA06BufferG0VAA9ContainerVnF : $@convention(thin) (@owned Container) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s39explicit_lifetime_dependence_specifiers16getConsumingViewyAA06BufferG0VAA9ContainerVnF : $@convention(thin) (@owned Container) -> @lifetime(copy 0) @owned BufferView {
@lifetime(x) @lifetime(copy x)
func getConsumingView(_ x: consuming Container) -> BufferView { func getConsumingView(_ x: consuming Container) -> BufferView {
let bv = BufferView(independent: x.ptr) let bv = BufferView(independent: x.ptr)
return _overrideLifetime(bv, copying: x) return _overrideLifetime(bv, copying: x)

View File

@@ -18,7 +18,7 @@ internal func _overrideLifetime<
} }
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(
@@ -43,16 +43,19 @@ struct BufferView : ~Escapable {
self.c = c self.c = c
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2ChcfC : $@convention(method) (@guaranteed BufferView, @thin BufferView.Type) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2ChcfC : $@convention(method) (@guaranteed BufferView, @thin BufferView.Type) -> @lifetime(copy 0) @owned BufferView {
@lifetime(copy otherBV)
init(_ otherBV: borrowing BufferView) { init(_ otherBV: borrowing BufferView) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2CcfC : $@convention(method) (@owned BufferView, @thin BufferView.Type) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyA2CcfC : $@convention(method) (@owned BufferView, @thin BufferView.Type) -> @lifetime(copy 0) @owned BufferView {
@lifetime(copy otherBV)
init(_ otherBV: consuming BufferView) { init(_ otherBV: consuming BufferView) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyACSW_SaySiGhtcfC : $@convention(method) (UnsafeRawBufferPointer, @guaranteed Array<Int>, @thin BufferView.Type) -> @lifetime(borrow 1) @owned BufferView { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence10BufferViewVyACSW_SaySiGhtcfC : $@convention(method) (UnsafeRawBufferPointer, @guaranteed Array<Int>, @thin BufferView.Type) -> @lifetime(borrow 0) @owned BufferView {
@lifetime(borrow ptr)
init(_ ptr: UnsafeRawBufferPointer, _ a: borrowing Array<Int>) { init(_ ptr: UnsafeRawBufferPointer, _ a: borrowing Array<Int>) {
self.ptr = ptr self.ptr = ptr
self.c = a.count self.c = a.count
@@ -80,15 +83,18 @@ func testBasic() {
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence6deriveyAA10BufferViewVADF : $@convention(thin) (@guaranteed BufferView) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence6deriveyAA10BufferViewVADF : $@convention(thin) (@guaranteed BufferView) -> @lifetime(copy 0) @owned BufferView {
@lifetime(copy x)
func derive(_ x: borrowing BufferView) -> BufferView { func derive(_ x: borrowing BufferView) -> BufferView {
return BufferView(x.ptr, x.c) return BufferView(x.ptr, x.c)
} }
@lifetime(copy x)
func derive(_ unused: Int, _ x: borrowing BufferView) -> BufferView { func derive(_ unused: Int, _ x: borrowing BufferView) -> BufferView {
return BufferView(independent: x.ptr, x.c) return BufferView(independent: x.ptr, x.c)
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence16consumeAndCreateyAA10BufferViewVADnF : $@convention(thin) (@owned BufferView) -> @lifetime(copy 0) @owned BufferView { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence16consumeAndCreateyAA10BufferViewVADnF : $@convention(thin) (@owned BufferView) -> @lifetime(copy 0) @owned BufferView {
@lifetime(copy x)
func consumeAndCreate(_ x: consuming BufferView) -> BufferView { func consumeAndCreate(_ x: consuming BufferView) -> BufferView {
let bv = BufferView(independent: x.ptr, x.c) let bv = BufferView(independent: x.ptr, x.c)
return _overrideLifetime(bv, copying: x) return _overrideLifetime(bv, copying: x)
@@ -100,24 +106,29 @@ struct Wrapper : ~Escapable {
var _view: BufferView var _view: BufferView
var view: BufferView { var view: BufferView {
// CHECK: sil hidden @$s28implicit_lifetime_dependence7WrapperV4viewAA10BufferViewVvr : $@yield_once @convention(method) (@guaranteed Wrapper) -> @lifetime(copy 0) @yields @guaranteed BufferView { // CHECK: sil hidden @$s28implicit_lifetime_dependence7WrapperV4viewAA10BufferViewVvr : $@yield_once @convention(method) (@guaranteed Wrapper) -> @lifetime(copy 0) @yields @guaranteed BufferView {
@lifetime(copy self)
_read { _read {
yield _view yield _view
} }
// CHECK: sil hidden @$s28implicit_lifetime_dependence7WrapperV4viewAA10BufferViewVvM : $@yield_once @convention(method) (@inout Wrapper) -> @lifetime(copy 0) @yields @inout BufferView { // CHECK: sil hidden @$s28implicit_lifetime_dependence7WrapperV4viewAA10BufferViewVvM : $@yield_once @convention(method) (@inout Wrapper) -> @lifetime(borrow 0) @yields @inout BufferView {
@lifetime(borrow self)
_modify { _modify {
yield &_view yield &_view
} }
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperVyAcA10BufferViewVcfC : $@convention(method) (@owned BufferView, @thin Wrapper.Type) -> @lifetime(copy 0) @owned Wrapper { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperVyAcA10BufferViewVcfC : $@convention(method) (@owned BufferView, @thin Wrapper.Type) -> @lifetime(copy 0) @owned Wrapper {
@lifetime(copy view)
init(_ view: consuming BufferView) { init(_ view: consuming BufferView) {
self._view = view self._view = view
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperV8getView1AA10BufferViewVyKF : $@convention(method) (@guaranteed Wrapper) -> @lifetime(copy 0) (@owned BufferView, @error any Error) { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperV8getView1AA10BufferViewVyKF : $@convention(method) (@guaranteed Wrapper) -> @lifetime(copy 0) (@owned BufferView, @error any Error) {
@lifetime(copy self)
borrowing func getView1() throws -> BufferView { borrowing func getView1() throws -> BufferView {
return _view return _view
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperV8getView2AA10BufferViewVyYaKF : $@convention(method) @async (@owned Wrapper) -> @lifetime(copy 0) (@owned BufferView, @error any Error) { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7WrapperV8getView2AA10BufferViewVyYaKF : $@convention(method) @async (@owned Wrapper) -> @lifetime(copy 0) (@owned BufferView, @error any Error) {
@lifetime(copy self)
consuming func getView2() async throws -> BufferView { consuming func getView2() async throws -> BufferView {
return _view return _view
} }
@@ -185,6 +196,7 @@ struct GenericBufferView<Element> : ~Escapable {
} }
// CHECK: sil hidden @$s28implicit_lifetime_dependence17GenericBufferViewVyACyxGAA9FakeRangeVySVGcig : $@convention(method) <Element> (FakeRange<UnsafeRawPointer>, @guaranteed GenericBufferView<Element>) -> @lifetime(copy 1) @owned GenericBufferView<Element> { // CHECK: sil hidden @$s28implicit_lifetime_dependence17GenericBufferViewVyACyxGAA9FakeRangeVySVGcig : $@convention(method) <Element> (FakeRange<UnsafeRawPointer>, @guaranteed GenericBufferView<Element>) -> @lifetime(copy 1) @owned GenericBufferView<Element> {
subscript(bounds: FakeRange<Pointer>) -> Self { subscript(bounds: FakeRange<Pointer>) -> Self {
@lifetime(copy self)
get { get {
let pointer = UnsafeRawPointer(bounds.lowerBound) let pointer = UnsafeRawPointer(bounds.lowerBound)
let result = GenericBufferView( let result = GenericBufferView(
@@ -198,6 +210,7 @@ struct GenericBufferView<Element> : ~Escapable {
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence23tupleLifetimeDependenceyAA10BufferViewV_ADtADF : $@convention(thin) (@guaranteed BufferView) -> @lifetime(copy 0) (@owned BufferView, @owned BufferView) { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence23tupleLifetimeDependenceyAA10BufferViewV_ADtADF : $@convention(thin) (@guaranteed BufferView) -> @lifetime(copy 0) (@owned BufferView, @owned BufferView) {
@lifetime(copy x)
func tupleLifetimeDependence(_ x: borrowing BufferView) -> (BufferView, BufferView) { func tupleLifetimeDependence(_ x: borrowing BufferView) -> (BufferView, BufferView) {
return (BufferView(x.ptr, x.c), BufferView(x.ptr, x.c)) return (BufferView(x.ptr, x.c), BufferView(x.ptr, x.c))
} }
@@ -206,27 +219,31 @@ public struct OuterNE: ~Escapable {
// A public property generates an implicit setter with an infered dependence on 'newValue'. // A public property generates an implicit setter with an infered dependence on 'newValue'.
// //
// [inner1.setter] // [inner1.setter]
// CHECK-LABEL: sil [transparent] @$s28implicit_lifetime_dependence7OuterNEV6inner1AC05InnerE0Vvs : $@convention(method) (@owned OuterNE.InnerNE, @lifetime(copy 0) @inout OuterNE) -> () { // CHECK-LABEL: sil [transparent] @$s28implicit_lifetime_dependence7OuterNEV6inner1AC05InnerE0Vvs : $@convention(method) (@owned OuterNE.InnerNE, @lifetime(copy 0, copy 1) @inout OuterNE) -> () {
public var inner1: InnerNE public var inner1: InnerNE
// Explicit setter with an infered dependence on 'newValue'. // Explicit setter with an infered dependence on 'newValue'.
public var inner2: InnerNE { public var inner2: InnerNE {
@lifetime(copy self)
get { inner1 } get { inner1 }
@lifetime(self: copy newValue)
set { inner1 = newValue } set { inner1 = newValue }
} }
public struct InnerNE: ~Escapable { public struct InnerNE: ~Escapable {
@lifetime(copy owner)
init<Owner: ~Escapable & ~Copyable>( init<Owner: ~Escapable & ~Copyable>(
owner: borrowing Owner owner: borrowing Owner
) {} ) {}
} }
@lifetime(copy owner)
init<Owner: ~Copyable & ~Escapable>(owner: borrowing Owner) { init<Owner: ~Copyable & ~Escapable>(owner: borrowing Owner) {
self.inner1 = InnerNE(owner: owner) self.inner1 = InnerNE(owner: owner)
} }
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7OuterNEV8setInner5valueyAC0gE0V_tF : $@convention(method) (@guaranteed OuterNE.InnerNE, @lifetime(copy 0) @inout OuterNE) -> () { // CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence7OuterNEV8setInner5valueyAC0gE0V_tF : $@convention(method) (@guaranteed OuterNE.InnerNE, @lifetime(copy 0) @inout OuterNE) -> () {
@lifetime(self: value) @lifetime(self: copy value)
mutating func setInner(value: InnerNE) { mutating func setInner(value: InnerNE) {
self.inner1 = value self.inner1 = value
} }

View File

@@ -8,6 +8,7 @@
public struct Span<Element> : ~Escapable { public struct Span<Element> : ~Escapable {
private var baseAddress: UnsafeRawPointer private var baseAddress: UnsafeRawPointer
public let count: Int public let count: Int
@lifetime(copy owner)
public init<Owner: ~Copyable & ~Escapable>( public init<Owner: ~Copyable & ~Escapable>(
baseAddress: UnsafeRawPointer, baseAddress: UnsafeRawPointer,
count: Int, count: Int,

View File

@@ -18,7 +18,7 @@ internal func _overrideLifetime<
} }
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(
@@ -83,7 +83,7 @@ public struct Span<Element> : ~Escapable {
public let count: Int public let count: Int
private var baseAddress: UnsafeRawPointer { start._rawValue } private var baseAddress: UnsafeRawPointer { start._rawValue }
// CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV11baseAddress5count9dependsOnACyxGSV_Siqd__htcRi_d__Ri0_d__lufC : $@convention(method) <Element><Owner where Owner : ~Copyable, Owner : ~Escapable> (UnsafeRawPointer, Int, @in_guaranteed Owner, @thin Span<Element>.Type) -> @lifetime(copy 2) @owned Span<Element> { // CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV11baseAddress5count9dependsOnACyxGSV_Siqd__htcRi_d__Ri0_d__lufC : $@convention(method) <Element><Owner where Owner : ~Copyable, Owner : ~Escapable> (UnsafeRawPointer, Int, @in_guaranteed Owner, @thin Span<Element>.Type) -> @lifetime(copy 2) @owned Span<Element> {
@lifetime(owner) @lifetime(copy owner)
public init<Owner: ~Copyable & ~Escapable>( public init<Owner: ~Copyable & ~Escapable>(
baseAddress: UnsafeRawPointer, baseAddress: UnsafeRawPointer,
count: Int, count: Int,
@@ -94,7 +94,7 @@ public struct Span<Element> : ~Escapable {
) )
} }
// CHECK-LABEL: sil hidden @$s025lifetime_dependence_span_A5_attr4SpanV5start5count9dependsOnACyxGAA0E5IndexVyxG_Siqd__htcRi_d__Ri0_d__lufC : $@convention(method) <Element><Owner where Owner : ~Copyable, Owner : ~Escapable> (SpanIndex<Element>, Int, @in_guaranteed Owner, @thin Span<Element>.Type) -> @lifetime(copy 2) @owned Span<Element> { // CHECK-LABEL: sil hidden @$s025lifetime_dependence_span_A5_attr4SpanV5start5count9dependsOnACyxGAA0E5IndexVyxG_Siqd__htcRi_d__Ri0_d__lufC : $@convention(method) <Element><Owner where Owner : ~Copyable, Owner : ~Escapable> (SpanIndex<Element>, Int, @in_guaranteed Owner, @thin Span<Element>.Type) -> @lifetime(copy 2) @owned Span<Element> {
@lifetime(owner) @lifetime(copy owner)
init<Owner: ~Copyable & ~Escapable>( init<Owner: ~Copyable & ~Escapable>(
start index: SpanIndex<Element>, start index: SpanIndex<Element>,
count: Int, count: Int,
@@ -150,7 +150,7 @@ extension Span {
// CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanVyACyxGAA9FakeRangeVyAA0E5IndexVyxGGcig : $@convention(method) <Element> (FakeRange<SpanIndex<Element>>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> { // CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanVyACyxGAA9FakeRangeVyAA0E5IndexVyxGGcig : $@convention(method) <Element> (FakeRange<SpanIndex<Element>>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> {
public subscript(bounds: FakeRange<SpanIndex<Element>>) -> Self { public subscript(bounds: FakeRange<SpanIndex<Element>>) -> Self {
@lifetime(self) @lifetime(copy self)
get { get {
let span = Span( let span = Span(
start: bounds.lowerBound, start: bounds.lowerBound,
@@ -161,7 +161,7 @@ extension Span {
} }
// CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefix4upToACyxGAA0E5IndexVyxG_tF : $@convention(method) <Element> (SpanIndex<Element>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> { // CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefix4upToACyxGAA0E5IndexVyxG_tF : $@convention(method) <Element> (SpanIndex<Element>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> {
@lifetime(self) @lifetime(copy self)
borrowing public func prefix(upTo index: SpanIndex<Element>) -> Self { borrowing public func prefix(upTo index: SpanIndex<Element>) -> Self {
index == startIndex index == startIndex
? Self(start: start, count: 0, dependsOn: copy self) ? Self(start: start, count: 0, dependsOn: copy self)
@@ -169,14 +169,14 @@ extension Span {
} }
// CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefix7throughACyxGAA0E5IndexVyxG_tF : $@convention(method) <Element> (SpanIndex<Element>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> { // CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefix7throughACyxGAA0E5IndexVyxG_tF : $@convention(method) <Element> (SpanIndex<Element>, @guaranteed Span<Element>) -> @lifetime(copy 1) @owned Span<Element> {
@lifetime(self) @lifetime(copy self)
borrowing public func prefix(through index: Index) -> Self { borrowing public func prefix(through index: Index) -> Self {
let nc = distance(from: startIndex, to: index) &+ 1 let nc = distance(from: startIndex, to: index) &+ 1
return Self(start: start, count: nc, dependsOn: copy self) return Self(start: start, count: nc, dependsOn: copy self)
} }
// CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefixyACyxGSiF : $@convention(method) <Element> (Int, @owned Span<Element>) -> @lifetime(copy 1) @owned Span<Element> { // CHECK-LABEL: sil @$s025lifetime_dependence_span_A5_attr4SpanV6prefixyACyxGSiF : $@convention(method) <Element> (Int, @owned Span<Element>) -> @lifetime(copy 1) @owned Span<Element> {
@lifetime(self) @lifetime(copy self)
consuming public func prefix(_ maxLength: Int) -> Self { consuming public func prefix(_ maxLength: Int) -> Self {
precondition(maxLength >= 0, "Can't have a prefix of negative length.") precondition(maxLength >= 0, "Can't have a prefix of negative length.")
let nc = maxLength < count ? maxLength : count let nc = maxLength < count ? maxLength : count

View File

@@ -7,9 +7,11 @@
// RUN: -module-name Swift \ // RUN: -module-name Swift \
// RUN: -disable-availability-checking \ // RUN: -disable-availability-checking \
// RUN: -enable-experimental-feature BuiltinModule \ // RUN: -enable-experimental-feature BuiltinModule \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -enable-builtin-module // RUN: -enable-builtin-module
// REQUIRES: swift_feature_BuiltinModule // REQUIRES: swift_feature_BuiltinModule
// REQUIRES: swift_feature_LifetimeDependence
// Force verification of TypeLowering's isTrivial. // Force verification of TypeLowering's isTrivial.

View File

@@ -135,7 +135,7 @@ func check(_ t: borrowing any NoEscapeP & ~Escapable) {}
// CHECK: sil hidden [ossa] @$s4main5checkyyAA9NoEscapeP_pRi0_s_XPnF : $@convention(thin) (@in any NoEscapeP & ~Escapable) -> () { // CHECK: sil hidden [ossa] @$s4main5checkyyAA9NoEscapeP_pRi0_s_XPnF : $@convention(thin) (@in any NoEscapeP & ~Escapable) -> () {
func check(_ t: consuming any NoEscapeP & ~Escapable) {} func check(_ t: consuming any NoEscapeP & ~Escapable) {}
// CHECK: sil hidden [ossa] @$s4main5checkyyAA9NoEscapeP_pRi0_s_XPzF : $@convention(thin) (@inout any NoEscapeP & ~Escapable) -> () { // CHECK: sil hidden [ossa] @$s4main5checkyyAA9NoEscapeP_pRi0_s_XPzF : $@convention(thin) (@lifetime(copy 0) @inout any NoEscapeP & ~Escapable) -> () {
func check(_ t: inout any NoEscapeP & ~Escapable) {} func check(_ t: inout any NoEscapeP & ~Escapable) {}
// MARK: conditionally Copyable & Escapable SILGen // MARK: conditionally Copyable & Escapable SILGen

View File

@@ -25,7 +25,7 @@ internal func _overrideLifetime<
@_unsafeNonescapableResult @_unsafeNonescapableResult
@_alwaysEmitIntoClient @_alwaysEmitIntoClient
@_transparent @_transparent
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(

View File

@@ -13,6 +13,7 @@ struct View : ~Escapable {
self.ptr = ptr self.ptr = ptr
self.c = c self.c = c
} }
@lifetime(copy otherBV)
init(_ otherBV: borrowing View) { init(_ otherBV: borrowing View) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
@@ -23,6 +24,7 @@ struct View : ~Escapable {
} }
// This overload requires a separate label because overloading // This overload requires a separate label because overloading
// on borrowing/consuming attributes is not allowed // on borrowing/consuming attributes is not allowed
@lifetime(copy k)
init(consumingView k: consuming View) { init(consumingView k: consuming View) {
self.ptr = k.ptr self.ptr = k.ptr
self.c = k.c self.c = k.c
@@ -34,13 +36,16 @@ struct Wrapper : ~Escapable {
// Nested coroutine access. // Nested coroutine access.
var view: View { var view: View {
@lifetime(copy self)
_read { _read {
yield _view yield _view
} }
@lifetime(borrow self)
_modify { _modify {
yield &_view yield &_view
} }
} }
@lifetime(copy view)
init(_ view: consuming View) { init(_ view: consuming View) {
self._view = view self._view = view
} }

View File

@@ -28,6 +28,7 @@ struct Span<T>: ~Escapable {
struct Wrapper<T: BitwiseCopyable>: ~Escapable { struct Wrapper<T: BitwiseCopyable>: ~Escapable {
private let span: Span<T> private let span: Span<T>
@lifetime(copy span)
init(span: borrowing Span<T>) { init(span: borrowing Span<T>) {
self.span = copy span self.span = copy span
} }
@@ -41,6 +42,7 @@ struct SuperWrapper<T: BitwiseCopyable>: ~Escapable {
// Make sure that LocalVariableUtils can successfully analyze 'self'. That's required to determine that the assignment // Make sure that LocalVariableUtils can successfully analyze 'self'. That's required to determine that the assignment
// of `wrapper` is returned without escaping // of `wrapper` is returned without escaping
@lifetime(copy span)
init(span: borrowing Span<T>) { init(span: borrowing Span<T>) {
self.wrapper = Wrapper(span: span) self.wrapper = Wrapper(span: span)
} }

View File

@@ -28,6 +28,7 @@ struct Span<T>: ~Escapable {
struct Wrapper<T: BitwiseCopyable>: ~Escapable { struct Wrapper<T: BitwiseCopyable>: ~Escapable {
private let span: Span<T> private let span: Span<T>
@lifetime(copy span)
init(span: borrowing Span<T>) { init(span: borrowing Span<T>) {
self.span = copy span self.span = copy span
} }
@@ -41,6 +42,7 @@ struct SuperWrapper<T: BitwiseCopyable>: ~Escapable {
// Make sure that LocalVariableUtils can successfully analyze 'self'. That's required to determine that the assignment // Make sure that LocalVariableUtils can successfully analyze 'self'. That's required to determine that the assignment
// of `wrapper` is returned without escaping // of `wrapper` is returned without escaping
@lifetime(copy span)
init(span: borrowing Span<T>) { init(span: borrowing Span<T>) {
self.wrapper = Wrapper(span: span) self.wrapper = Wrapper(span: span)
} }

View File

@@ -45,7 +45,7 @@ struct MBV : ~Escapable, ~Copyable {
} }
// Requires a borrow. // Requires a borrow.
@lifetime(self) @lifetime(copy self)
borrowing func getBV() -> BV { borrowing func getBV() -> BV {
BV(p, i) BV(p, i)
} }
@@ -55,25 +55,26 @@ struct MBV : ~Escapable, ~Copyable {
struct NEBV : ~Escapable { struct NEBV : ~Escapable {
var bv: BV var bv: BV
@lifetime(copy bv)
init(_ bv: consuming BV) { init(_ bv: consuming BV) {
self.bv = bv self.bv = bv
} }
} }
// Propagate a borrow. // Propagate a borrow.
@lifetime(container) @lifetime(copy container)
func bv_get_borrow(container: borrowing MBV) -> BV { func bv_get_borrow(container: borrowing MBV) -> BV {
container.getBV() container.getBV()
} }
// Copy a borrow. // Copy a borrow.
@lifetime(container) @lifetime(copy container)
func bv_get_copy(container: borrowing MBV) -> BV { func bv_get_copy(container: borrowing MBV) -> BV {
return container.getBV() return container.getBV()
} }
// Recognize nested accesses as part of the same dependence scope. // Recognize nested accesses as part of the same dependence scope.
@lifetime(container) @lifetime(copy container)
func bv_get_mutate(container: inout MBV) -> BV { func bv_get_mutate(container: inout MBV) -> BV {
container.getBV() container.getBV()
} }

View File

@@ -60,6 +60,7 @@ struct NE : ~Escapable {
} }
} }
@lifetime(copy container)
func bv_get_consume(container: consuming NE) -> BV { func bv_get_consume(container: consuming NE) -> BV {
return container.getBV() // expected-error {{lifetime-dependent value escapes its scope}} return container.getBV() // expected-error {{lifetime-dependent value escapes its scope}}
// expected-note @-1{{it depends on this scoped access to variable 'container'}} // expected-note @-1{{it depends on this scoped access to variable 'container'}}
@@ -70,12 +71,12 @@ struct Wrapper : ~Escapable {
let bv: BV let bv: BV
} }
@lifetime(bv2) @lifetime(copy bv2)
func bv_incorrect_annotation1(_ bv1: borrowing BV, _ bv2: borrowing BV) -> BV { // expected-error {{lifetime-dependent variable 'bv1' escapes its scope}} func bv_incorrect_annotation1(_ bv1: borrowing BV, _ bv2: borrowing BV) -> BV { // expected-error {{lifetime-dependent variable 'bv1' escapes its scope}}
return copy bv1 // expected-note @-1{{it depends on the lifetime of argument 'bv1'}} return copy bv1 // expected-note @-1{{it depends on the lifetime of argument 'bv1'}}
} // expected-note @-1{{this use causes the lifetime-dependent value to escape}} } // expected-note @-1{{this use causes the lifetime-dependent value to escape}}
@lifetime(w2) @lifetime(copy w2)
func bv_incorrect_annotation2(_ w1: borrowing Wrapper, _ w2: borrowing Wrapper) -> BV { // expected-error {{lifetime-dependent variable 'w1' escapes its scope}} func bv_incorrect_annotation2(_ w1: borrowing Wrapper, _ w2: borrowing Wrapper) -> BV { // expected-error {{lifetime-dependent variable 'w1' escapes its scope}}
return w1.bv // expected-note @-1{{it depends on the lifetime of argument 'w1'}} return w1.bv // expected-note @-1{{it depends on the lifetime of argument 'w1'}}
} // expected-note @-1{{this use causes the lifetime-dependent value to escape}} } // expected-note @-1{{this use causes the lifetime-dependent value to escape}}

View File

@@ -17,7 +17,7 @@ struct BV : ~Escapable {
} }
} }
@lifetime(bv) @lifetime(copy bv)
func bv_copy(_ bv: borrowing BV) -> BV { func bv_copy(_ bv: borrowing BV) -> BV {
copy bv copy bv
} }
@@ -30,7 +30,7 @@ public struct NEInt: ~Escapable {
var i: Int var i: Int
// Test yielding an address. // Test yielding an address.
// CHECK-LABEL: sil hidden @$s4test5NEIntV5ipropSivM : $@yield_once @convention(method) (@inout NEInt) -> @yields @inout Int { // CHECK-LABEL: sil hidden @$s4test5NEIntV5ipropSivM : $@yield_once @convention(method) (@inout NEInt) -> @lifetime(borrow 0) @yields @inout Int
// CHECK: bb0(%0 : $*NEInt): // CHECK: bb0(%0 : $*NEInt):
// CHECK: [[A:%.*]] = begin_access [modify] [static] %0 : $*NEInt // CHECK: [[A:%.*]] = begin_access [modify] [static] %0 : $*NEInt
// CHECK: [[E:%.*]] = struct_element_addr [[A]] : $*NEInt, #NEInt.i // CHECK: [[E:%.*]] = struct_element_addr [[A]] : $*NEInt, #NEInt.i
@@ -39,7 +39,9 @@ public struct NEInt: ~Escapable {
// CHECK: end_access [[A]] : $*NEInt // CHECK: end_access [[A]] : $*NEInt
// CHECK-LABEL: } // end sil function '$s4test5NEIntV5ipropSivM' // CHECK-LABEL: } // end sil function '$s4test5NEIntV5ipropSivM'
var iprop: Int { var iprop: Int {
@lifetime(copy self)
_read { yield i } _read { yield i }
@lifetime(borrow self)
_modify { yield &i } _modify { yield &i }
} }
@@ -56,6 +58,7 @@ public enum NEOptional<Wrapped: ~Escapable>: ~Escapable {
extension NEOptional where Wrapped: ~Escapable { extension NEOptional where Wrapped: ~Escapable {
// Test that enum initialization passes diagnostics. // Test that enum initialization passes diagnostics.
@lifetime(copy some)
public init(_ some: consuming Wrapped) { self = .some(some) } public init(_ some: consuming Wrapped) { self = .some(some) }
} }

View File

@@ -52,7 +52,7 @@ struct NCInt: ~Copyable {
struct NEInt: ~Escapable { struct NEInt: ~Escapable {
let value: Builtin.Int64 let value: Builtin.Int64
@lifetime(o) @lifetime(copy o)
init<O: ~Copyable & ~Escapable>(v: Builtin.Int64, o: borrowing O) { init<O: ~Copyable & ~Escapable>(v: Builtin.Int64, o: borrowing O) {
self.value = v self.value = v
} }
@@ -64,17 +64,17 @@ struct NEInt: ~Escapable {
} }
} }
@lifetime(ne) @lifetime(copy ne)
public func consume_indirect<NE: ~Escapable>(ne: consuming NE) -> NE { public func consume_indirect<NE: ~Escapable>(ne: consuming NE) -> NE {
return ne return ne
} }
@lifetime(ne) @lifetime(copy ne)
public func copy_indirect<NE: ~Escapable>(ne: borrowing NE) -> NE { public func copy_indirect<NE: ~Escapable>(ne: borrowing NE) -> NE {
return copy ne return copy ne
} }
@lifetime(ne) @lifetime(copy ne)
public func copy_inout<NE: ~Escapable>(ne: inout NE) -> NE { public func copy_inout<NE: ~Escapable>(ne: inout NE) -> NE {
return copy ne return copy ne
} }

View File

@@ -11,7 +11,7 @@
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is
// hidden within the function body. // hidden within the function body.
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>( func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
dependent: consuming T, dependsOn source: borrowing U) dependent: consuming T, dependsOn source: borrowing U)
-> T { -> T {
@@ -34,7 +34,7 @@ struct BV : ~Escapable {
self.i = i self.i = i
} }
@lifetime(self) @lifetime(copy self)
consuming func derive() -> BV { consuming func derive() -> BV {
// Technically, this "new" view does not depend on the 'view' argument. // Technically, this "new" view does not depend on the 'view' argument.
// This unsafely creates a new view with no dependence. // This unsafely creates a new view with no dependence.
@@ -48,14 +48,17 @@ struct NEBV : ~Escapable {
var bv: BV var bv: BV
// Test lifetime inheritance through initialization. // Test lifetime inheritance through initialization.
@lifetime(copy bv)
init(_ bv: consuming BV) { init(_ bv: consuming BV) {
self.bv = bv self.bv = bv
} }
var view: BV { var view: BV {
@lifetime(copy self)
_read { _read {
yield bv yield bv
} }
@lifetime(borrow self)
_modify { _modify {
yield &bv yield &bv
} }
@@ -68,18 +71,18 @@ struct NEBV : ~Escapable {
} }
// Test lifetime inheritance through chained consumes. // Test lifetime inheritance through chained consumes.
@lifetime(bv) @lifetime(copy bv)
func bv_derive(bv: consuming BV) -> BV { func bv_derive(bv: consuming BV) -> BV {
bv.derive() bv.derive()
} }
// Test lifetime inheritance through stored properties. // Test lifetime inheritance through stored properties.
@lifetime(nebv) @lifetime(copy nebv)
func ne_extract_member(nebv: consuming NEBV) -> BV { func ne_extract_member(nebv: consuming NEBV) -> BV {
return nebv.bv return nebv.bv
} }
@lifetime(nebv) @lifetime(copy nebv)
func ne_yield_member(nebv: consuming NEBV) -> BV { func ne_yield_member(nebv: consuming NEBV) -> BV {
return nebv.view return nebv.view
} }

View File

@@ -11,7 +11,7 @@
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is
// hidden within the function body. // hidden within the function body.
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>( func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
dependent: consuming T, dependsOn source: borrowing U) dependent: consuming T, dependsOn source: borrowing U)
-> T { -> T {
@@ -46,7 +46,7 @@ struct BV : ~Escapable {
struct NE : ~Escapable { struct NE : ~Escapable {
var bv: BV var bv: BV
@lifetime(bv) @lifetime(copy bv)
init(_ bv: consuming BV) { init(_ bv: consuming BV) {
self.bv = bv self.bv = bv
} }

View File

@@ -27,7 +27,7 @@ internal func _overrideLifetime<
/// the `source` argument. /// the `source` argument.
@_unsafeNonescapableResult @_unsafeNonescapableResult
@_transparent @_transparent
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(
@@ -91,7 +91,10 @@ struct MutableSpan : ~Escapable, ~Copyable {
} }
} }
var iterator: Iter { Iter(base: base, count: count) } var iterator: Iter {
@lifetime(copy self)
get { Iter(base: base, count: count) }
}
} }
extension Array where Element == Int { extension Array where Element == Int {

View File

@@ -38,6 +38,7 @@ extension Nillable: ExpressibleByNilLiteral where Wrapped: ~Copyable & ~Escapabl
extension Nillable where Wrapped: ~Copyable & ~Escapable { extension Nillable where Wrapped: ~Copyable & ~Escapable {
@_transparent @_transparent
@lifetime(copy some)
public init(_ some: consuming Wrapped) { self = .some(some) } public init(_ some: consuming Wrapped) { self = .some(some) }
} }

View File

@@ -11,7 +11,7 @@
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence should be expressed by a builtin that is
// hidden within the function body. // hidden within the function body.
@_unsafeNonescapableResult @_unsafeNonescapableResult
@lifetime(source) @lifetime(copy source)
func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>( func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
dependent: consuming T, dependsOn source: borrowing U) dependent: consuming T, dependsOn source: borrowing U)
-> T { -> T {
@@ -38,7 +38,7 @@ struct BV : ~Escapable {
public var isEmpty: Bool { i == 0 } public var isEmpty: Bool { i == 0 }
// Test consuming `self` // Test consuming `self`
@lifetime(self) @lifetime(copy self)
consuming func derive() -> BV { consuming func derive() -> BV {
// Technically, this "new" view does not depend on the 'view' argument. // Technically, this "new" view does not depend on the 'view' argument.
// This unsafely creates a new view with no dependence. // This unsafely creates a new view with no dependence.
@@ -51,7 +51,7 @@ struct BV : ~Escapable {
struct NE { struct NE {
var bv: BV var bv: BV
@lifetime(bv) @lifetime(copy bv)
init(_ bv: BV) { init(_ bv: BV) {
self.bv = bv self.bv = bv
} }

View File

@@ -33,44 +33,47 @@ struct NC : ~Copyable {
struct NE { struct NE {
var bv: BV var bv: BV
@lifetime(bv) @lifetime(copy bv)
init(_ bv: consuming BV) { init(_ bv: consuming BV) {
self.bv = bv self.bv = bv
} }
} }
func bv_assign_inout(bv: BV, other: inout BV) { // expected-error{{lifetime-dependent variable 'bv' escapes its scope}} @lifetime(other: copy bv)
// expected-note @-1 {{it depends on the lifetime of argument 'bv'}} func bv_assign_inout_copy(bv: BV, other: inout BV) {
other = bv // expected-note {{this use causes the lifetime-dependent value to escape}} other = bv // OK
} }
@lifetime(other: borrow bv)
func bv_assign_inout_borrow(bv: BV, other: inout BV) {
other = bv
}
@lifetime(bv: copy bv)
@lifetime(other: copy bv)
func bvmut_assign_inout(bv: inout BV, other: inout BV) { func bvmut_assign_inout(bv: inout BV, other: inout BV) {
other = bv // expected-error{{lifetime-dependent value escapes its scope}} other = bv
// expected-note @-2 {{it depends on the lifetime of argument 'bv'}}
// expected-note @-2 {{this use causes the lifetime-dependent value to escape}}
} }
@lifetime(other: copy bv)
func bvcons_assign_inout(bv: consuming BV, other: inout BV) { func bvcons_assign_inout(bv: consuming BV, other: inout BV) {
other = bv // expected-error{{lifetime-dependent value escapes its scope}} other = bv
// expected-note @-2 {{it depends on the lifetime of argument 'bv'}}
// expected-note @-2 {{this use causes the lifetime-dependent value to escape}}
} }
func bv_assign_field(bv: BV, other: inout NE) { // expected-error{{lifetime-dependent variable 'bv' escapes its scope}} @lifetime(other: copy bv)
// expected-note @-1 {{it depends on the lifetime of argument 'bv'}} func bv_assign_field(bv: BV, other: inout NE) {
other.bv = bv // expected-note {{this use causes the lifetime-dependent value to escape}} other.bv = bv
} }
@lifetime(bv: copy bv)
@lifetime(other: copy bv)
func bvmut_assign_field(bv: inout BV, other: inout NE) { func bvmut_assign_field(bv: inout BV, other: inout NE) {
other.bv = bv // expected-error{{lifetime-dependent value escapes its scope}} other.bv = bv
// expected-note @-2 {{it depends on the lifetime of argument 'bv'}}
// expected-note @-2 {{this use causes the lifetime-dependent value to escape}}
} }
@lifetime(other: copy bv)
func bvcons_assign_field(bv: consuming BV, other: inout NE) { func bvcons_assign_field(bv: consuming BV, other: inout NE) {
other.bv = bv // expected-error{{lifetime-dependent value escapes its scope}} other.bv = bv
// expected-note @-2 {{it depends on the lifetime of argument 'bv'}}
// expected-note @-2 {{this use causes the lifetime-dependent value to escape}}
} }
func bv_capture_escape(bv: BV) -> ()->Int { // expected-error{{lifetime-dependent variable 'bv' escapes its scope}} func bv_capture_escape(bv: BV) -> ()->Int { // expected-error{{lifetime-dependent variable 'bv' escapes its scope}}

View File

@@ -22,6 +22,7 @@ struct View : ~Escapable {
self.ptr = ptr self.ptr = ptr
self.c = c self.c = c
} }
@lifetime(copy otherBV)
init(_ otherBV: borrowing View) { init(_ otherBV: borrowing View) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
@@ -32,6 +33,7 @@ struct View : ~Escapable {
} }
// This overload requires a separate label because overloading // This overload requires a separate label because overloading
// on borrowing/consuming attributes is not allowed // on borrowing/consuming attributes is not allowed
@lifetime(copy k)
init(consumingView k: consuming View) { init(consumingView k: consuming View) {
self.ptr = k.ptr self.ptr = k.ptr
self.c = k.c self.c = k.c
@@ -46,6 +48,7 @@ struct MutableView : ~Copyable, ~Escapable {
self.ptr = ptr self.ptr = ptr
self.c = c self.c = c
} }
@lifetime(copy otherBV)
init(_ otherBV: borrowing View) { init(_ otherBV: borrowing View) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
@@ -63,7 +66,7 @@ func consume(_ o : consuming View) {}
func use(_ o : borrowing MutableView) {} func use(_ o : borrowing MutableView) {}
func consume(_ o : consuming MutableView) {} func consume(_ o : consuming MutableView) {}
@lifetime(x) @lifetime(copy x)
func getConsumingView(_ x: consuming View) -> View { func getConsumingView(_ x: consuming View) -> View {
return View(consumingView: x) return View(consumingView: x)
} }
@@ -190,13 +193,16 @@ func test8(_ a: Array<Int>) {
struct Wrapper : ~Escapable { struct Wrapper : ~Escapable {
var _view: View var _view: View
var view: View { var view: View {
@lifetime(copy self)
_read { _read {
yield _view yield _view
} }
@lifetime(borrow self)
_modify { _modify {
yield &_view yield &_view
} }
} }
@lifetime(copy view)
init(_ view: consuming View) { init(_ view: consuming View) {
self._view = view self._view = view
} }
@@ -212,6 +218,7 @@ func test9() {
} }
} }
@lifetime(copy x)
func getViewTuple(_ x: borrowing View) -> (View, View) { func getViewTuple(_ x: borrowing View) -> (View, View) {
return (View(x.ptr, x.c), View(x.ptr, x.c)) return (View(x.ptr, x.c), View(x.ptr, x.c))
} }
@@ -236,4 +243,5 @@ public func test10() {
func testPointeeDependenceOnMutablePointer(p: UnsafePointer<Int64>) { func testPointeeDependenceOnMutablePointer(p: UnsafePointer<Int64>) {
var ptr = p var ptr = p
_ = ptr.pointee _ = ptr.pointee
_ = ptr
} }

View File

@@ -33,7 +33,7 @@ internal func _overrideLifetime<
/// the `source` argument. /// the `source` argument.
@_unsafeNonescapableResult @_unsafeNonescapableResult
@_transparent @_transparent
@lifetime(source) @lifetime(copy source)
internal func _overrideLifetime< internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>( >(
@@ -83,6 +83,7 @@ public struct Span<T>: ~Escapable {
} }
extension Span { extension Span {
@lifetime(copy self)
consuming func dropFirst() -> Span<T> { consuming func dropFirst() -> Span<T> {
let nextPointer = self.base.flatMap { $0 + 1 } let nextPointer = self.base.flatMap { $0 + 1 }
let local = Span(base: nextPointer, count: self.count - 1) let local = Span(base: nextPointer, count: self.count - 1)
@@ -91,6 +92,7 @@ extension Span {
} }
extension Span { extension Span {
@lifetime(copy self)
mutating func droppingPrefix(length: Int) -> /* */ Span<T> { mutating func droppingPrefix(length: Int) -> /* */ Span<T> {
let oldBase = base let oldBase = base
let result = Span(base: oldBase, count: length) let result = Span(base: oldBase, count: length)
@@ -231,6 +233,7 @@ struct Outer {
func parse(_ span: Span<Int>) {} func parse(_ span: Span<Int>) {}
@lifetime(copy arg)
func copySpan<T>(_ arg: Span<T>) -> /* */ Span<T> { arg } func copySpan<T>(_ arg: Span<T>) -> /* */ Span<T> { arg }
@lifetime(borrow arg) @lifetime(borrow arg)
@@ -600,12 +603,3 @@ func testBorrowedAddressableIntReturn(arg: Holder) -> Span<Int> {
} // todo-note {{this use causes the lifetime-dependent value to escape}} } // todo-note {{this use causes the lifetime-dependent value to escape}}
*/ */
// =============================================================================
// Parameter dependencies
// =============================================================================
// rdar://146401190 ([nonescapable] implement non-inout parameter dependencies)
@lifetime(span: borrow holder)
func testParameterDep(holder: Holder, span: Span<Int>) {} // expected-error {{lifetime-dependent parameter must be 'inout'}}

View File

@@ -11,7 +11,7 @@
// TODO: uncomment the @lifetime annotations when we have component lifetimes. // TODO: uncomment the @lifetime annotations when we have component lifetimes.
// @lifetime(elements) // @lifetime(copy elements)
struct Span<T: ~Escapable>: ~Escapable { struct Span<T: ~Escapable>: ~Escapable {
// Pretend that 'element' is in separate storage. // Pretend that 'element' is in separate storage.
var element: T var element: T
@@ -22,7 +22,7 @@ struct Span<T: ~Escapable>: ~Escapable {
} }
} }
// @lifetime(elements) // @lifetime(copy elements)
extension Array { extension Array {
// @lifetime(span: borrow self) // @lifetime(span: borrow self)
// @lifetime(span.elements: copy self.elements) // @lifetime(span.elements: copy self.elements)
@@ -34,7 +34,7 @@ extension Array {
} }
// use 'scalars' instead of 'elements' to avoid confusion from nesting // use 'scalars' instead of 'elements' to avoid confusion from nesting
// @lifetime(scalars) // @lifetime(copy scalars)
struct Vec<T: ~Escapable>: ~Escapable { struct Vec<T: ~Escapable>: ~Escapable {
// Pretend that 't' is in separate storage. // Pretend that 't' is in separate storage.
var scalar: T var scalar: T

View File

@@ -64,11 +64,13 @@ struct TestCoroAccessorOfCoroAccessor<T : ~Escapable> : ~Copyable & ~Escapable {
var t: T var t: T
var inner: TestCoroAccessorOfCoroAccessor<T> { var inner: TestCoroAccessorOfCoroAccessor<T> {
@lifetime(copy self)
_read { _read {
fatalError() fatalError()
} }
} }
var outer: TestCoroAccessorOfCoroAccessor<T> { var outer: TestCoroAccessorOfCoroAccessor<T> {
@lifetime(copy self)
_read { _read {
yield inner yield inner
} }

View File

@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t) // RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/SpanExtras.swiftmodule %S/Inputs/SpanExtras.swift -enable-builtin-module -enable-experimental-feature LifetimeDependence -O // RUN: %target-swift-frontend -emit-module-path %t/SpanExtras.swiftmodule %S/Inputs/SpanExtras.swift -enable-builtin-module -enable-experimental-feature LifetimeDependence -O
// RUN: %target-swift-frontend -I %t -O -emit-sil %s -disable-availability-checking | %FileCheck %s --check-prefix=CHECK-SIL // RUN: %target-swift-frontend -I %t -O -emit-sil %s -enable-experimental-feature LifetimeDependence -disable-availability-checking | %FileCheck %s --check-prefix=CHECK-SIL
// RUN: %target-swift-frontend -I %t -O -emit-ir %s -disable-availability-checking | %FileCheck %s --check-prefix=CHECK-IR // RUN: %target-swift-frontend -I %t -O -emit-ir %s -enable-experimental-feature LifetimeDependence -disable-availability-checking | %FileCheck %s --check-prefix=CHECK-IR
// REQUIRES: swift_in_compiler // REQUIRES: swift_in_compiler
// REQUIRES: swift_feature_LifetimeDependence // REQUIRES: swift_feature_LifetimeDependence
@@ -44,6 +44,7 @@ public func span_zero_init(_ output: inout MutableSpan<Int>) {
// CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B14_copy_elemwiseyy10SpanExtras07MutableH0VySiGz_s0H0VySiGtF" // CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B14_copy_elemwiseyy10SpanExtras07MutableH0VySiGz_s0H0VySiGtF"
// CHECK-IR: vector.body // CHECK-IR: vector.body
// CHECK-IR: store <{{.*}}> // CHECK-IR: store <{{.*}}>
@lifetime(output: copy output, copy input)
public func span_copy_elemwise(_ output: inout MutableSpan<Int>, _ input: Span<Int>) { public func span_copy_elemwise(_ output: inout MutableSpan<Int>, _ input: Span<Int>) {
precondition(output.count >= input.count) precondition(output.count >= input.count)
for i in input.indices { for i in input.indices {
@@ -65,6 +66,7 @@ public func span_copy_elemwise(_ output: inout MutableSpan<Int>, _ input: Span<I
// CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B16_append_elemwiseyy10SpanExtras06OutputH0VySiGz_s0H0VySiGtF" // CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B16_append_elemwiseyy10SpanExtras06OutputH0VySiGz_s0H0VySiGtF"
// CHECK-IR: vector.body // CHECK-IR: vector.body
// CHECK-IR: store <{{.*}}> // CHECK-IR: store <{{.*}}>
@lifetime(output: copy output, copy input)
public func span_append_elemwise(_ output: inout OutputSpan<Int>, _ input: Span<Int>) { public func span_append_elemwise(_ output: inout OutputSpan<Int>, _ input: Span<Int>) {
for i in input.indices { for i in input.indices {
output.append(input[i]) output.append(input[i])
@@ -83,6 +85,7 @@ public func span_append_elemwise(_ output: inout OutputSpan<Int>, _ input: Span<
// CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B12_sum_wo_trapyy10SpanExtras07MutableI0VySiGz_s0I0VySiGAItF" // CHECK-IR: define {{.*}} void @"$s31mutable_span_bounds_check_tests0B12_sum_wo_trapyy10SpanExtras07MutableI0VySiGz_s0I0VySiGAItF"
// CHECK-IR: vector.body // CHECK-IR: vector.body
// CHECK-IR: store <{{.*}}> // CHECK-IR: store <{{.*}}>
@lifetime(output: copy output, copy input1, copy input2)
public func span_sum_wo_trap(_ output: inout MutableSpan<Int>, _ input1: Span<Int>, _ input2: Span<Int>) { public func span_sum_wo_trap(_ output: inout MutableSpan<Int>, _ input1: Span<Int>, _ input2: Span<Int>) {
precondition(input1.count == input2.count) precondition(input1.count == input2.count)
precondition(output.count == input1.count) precondition(output.count == input1.count)
@@ -97,7 +100,7 @@ public func span_sum_wo_trap(_ output: inout MutableSpan<Int>, _ input1: Span<In
// CHECK-SIL-NOT: cond_fail {{.*}}, "precondition failure" // CHECK-SIL-NOT: cond_fail {{.*}}, "precondition failure"
// CHECK-SIL: cond_br // CHECK-SIL: cond_br
// CHECK-SIL-LABEL: } // end sil function '$s31mutable_span_bounds_check_tests0B14_sum_with_trapyy10SpanExtras07MutableI0VySiGz_s0I0VySiGAItF' // CHECK-SIL-LABEL: } // end sil function '$s31mutable_span_bounds_check_tests0B14_sum_with_trapyy10SpanExtras07MutableI0VySiGz_s0I0VySiGAItF'
@lifetime(output: copy input1, copy input2)
public func span_sum_with_trap(_ output: inout MutableSpan<Int>, _ input1: Span<Int>, _ input2: Span<Int>) { public func span_sum_with_trap(_ output: inout MutableSpan<Int>, _ input1: Span<Int>, _ input2: Span<Int>) {
precondition(input1.count == input2.count) precondition(input1.count == input2.count)
precondition(output.count == input1.count) precondition(output.count == input1.count)

View File

@@ -328,6 +328,7 @@ public func mutate_span(_ v: inout Span<Int>) { }
// CHECK-SIL-NOT: cond_fail {{.*}}, "Index out of bounds" // CHECK-SIL-NOT: cond_fail {{.*}}, "Index out of bounds"
// CHECK-SIL: cond_br // CHECK-SIL: cond_br
// CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests06inout_A33_sum_iterate_to_unknown_with_trapySis4SpanVySiGz_SitF' // CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests06inout_A33_sum_iterate_to_unknown_with_trapySis4SpanVySiGz_SitF'
@lifetime(v: copy v)
public func inout_span_sum_iterate_to_unknown_with_trap(_ v: inout Span<Int>, _ n: Int) -> Int { public func inout_span_sum_iterate_to_unknown_with_trap(_ v: inout Span<Int>, _ n: Int) -> Int {
var sum = 0 var sum = 0
for i in 0...n { for i in 0...n {
@@ -342,6 +343,7 @@ public func inout_span_sum_iterate_to_unknown_with_trap(_ v: inout Span<Int>, _
// CHECK-SIL: cond_fail {{.*}}, "Index out of bounds" // CHECK-SIL: cond_fail {{.*}}, "Index out of bounds"
// CHECK-SIL: cond_br // CHECK-SIL: cond_br
// CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests06inout_A41_sum_iterate_to_unknown_with_trap_dontoptySis4SpanVySiGz_SitF' // CHECK-SIL-LABEL: } // end sil function '$s23span_bounds_check_tests06inout_A41_sum_iterate_to_unknown_with_trap_dontoptySis4SpanVySiGz_SitF'
@lifetime(v: copy v)
public func inout_span_sum_iterate_to_unknown_with_trap_dontopt(_ v: inout Span<Int>, _ n: Int) -> Int { public func inout_span_sum_iterate_to_unknown_with_trap_dontopt(_ v: inout Span<Int>, _ n: Int) -> Int {
var sum = 0 var sum = 0
for i in 0...n { for i in 0...n {

View File

@@ -1,10 +1,12 @@
// RUN: %target-typecheck-verify-swift \ // RUN: %target-typecheck-verify-swift \
// RUN: -disable-availability-checking \ // RUN: -disable-availability-checking \
// RUN: -enable-experimental-feature Sensitive \ // RUN: -enable-experimental-feature Sensitive \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -enable-builtin-module \ // RUN: -enable-builtin-module \
// RUN: -debug-diagnostic-names // RUN: -debug-diagnostic-names
// REQUIRES: swift_feature_Sensitive // REQUIRES: swift_feature_Sensitive
// REQUIRES: swift_feature_LifetimeDependence
//============================================================================== //==============================================================================
//===========================DEPENDENCY-FREE TESTS=(BEGIN)===================={{ //===========================DEPENDENCY-FREE TESTS=(BEGIN)===================={{
@@ -212,9 +214,7 @@ struct S_Explicit_With_2BitwiseCopyable_Generic_Optional<T : BitwiseCopyable> :
var o2: T? var o2: T?
} }
// TODO: When the standard library is built with NonescapableTypes, this should struct S_Explicit_Nonescapable : ~Escapable, BitwiseCopyable {}
// be uncommented.
//struct S_Explicit_Nonescapable : ~Escapable, BitwiseCopyable {}
struct S_Explicit_Noncopyable : ~Copyable, BitwiseCopyable {} // expected-error{{type_does_not_conform}} struct S_Explicit_Noncopyable : ~Copyable, BitwiseCopyable {} // expected-error{{type_does_not_conform}}

View File

@@ -1,7 +1,10 @@
// RUN: %target-typecheck-verify-swift \ // RUN: %target-typecheck-verify-swift \
// RUN: -enable-builtin-module \ // RUN: -enable-builtin-module \
// RUN: -enable-experimental-feature LifetimeDependence \
// RUN: -debug-diagnostic-names // RUN: -debug-diagnostic-names
// REQUIRES: swift_feature_LifetimeDependence
// This test file only exists in order to test without noncopyable_generics and can be deleted once that is always enabled. // This test file only exists in order to test without noncopyable_generics and can be deleted once that is always enabled.
@_nonescapable @_nonescapable

View File

@@ -12,7 +12,7 @@ struct BufferView : ~Escapable, ~Copyable {
} }
} }
struct ImplicitInit1 : ~Escapable { // expected-error{{cannot infer lifetime dependence on implicit initializer, no parameters found that are either ~Escapable or Escapable with a borrowing ownership}} struct ImplicitInit1 : ~Escapable {
let ptr: UnsafeRawBufferPointer let ptr: UnsafeRawBufferPointer
} }
@@ -20,20 +20,21 @@ struct ImplicitInit2 : ~Escapable, ~Copyable {
let mbv: BufferView let mbv: BufferView
} }
struct ImplicitInit3 : ~Escapable, ~Copyable { // expected-error{{cannot infer lifetime dependence on implicit initializer, multiple parameters qualifiy as a candidate}} struct ImplicitInit3 : ~Escapable, ~Copyable {
let mbv1: BufferView let mbv1: BufferView
let mbv2: BufferView let mbv2: BufferView
} }
func foo1() -> BufferView { // expected-error{{cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership}} func foo1() -> BufferView { // expected-error{{a function with a ~Escapable result needs a parameter to depend on}}
// expected-note@-1{{'@lifetime(immortal)' can be used to indicate that values produced by this initializer have no lifetime dependencies}}
return BufferView(nil, 0) return BufferView(nil, 0)
} }
func foo2(_ i: borrowing Int) -> BufferView { // expected-error{{cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership}} func foo2(_ i: borrowing Int) -> BufferView {
return BufferView(nil, 0) return BufferView(nil, 0)
} }
func foo3<T: BitwiseCopyable>(arg: borrowing T) -> BufferView { // expected-error{{cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership}} func foo3<T: BitwiseCopyable>(arg: borrowing T) -> BufferView {
return BufferView(nil, 0) return BufferView(nil, 0)
} }

View File

@@ -3,16 +3,16 @@
// REQUIRES: swift_feature_LifetimeDependence // REQUIRES: swift_feature_LifetimeDependence
struct NE : ~Escapable { struct NE : ~Escapable {
@lifetime(self) // expected-error{{invalid lifetime dependence on self in an initializer}} @lifetime(copy self) // expected-error{{invalid lifetime dependence specifier on non-existent self}}
init() {} init() {}
} }
@lifetime(nonexisting) // expected-error{{invalid parameter name specified 'nonexisting'}} @lifetime(copy nonexisting) // expected-error{{invalid parameter name specified 'nonexisting'}}
func invalidAttrOnNonExistingParam(_ ne: NE) -> NE { func invalidAttrOnNonExistingParam(_ ne: NE) -> NE {
ne ne
} }
@lifetime(self) // expected-error{{invalid lifetime dependence specifier on non-existent self}} @lifetime(copy self) // expected-error{{invalid lifetime dependence specifier on non-existent self}}
func invalidAttrOnNonExistingSelf(_ ne: NE) -> NE { func invalidAttrOnNonExistingSelf(_ ne: NE) -> NE {
ne ne
} }
@@ -22,7 +22,7 @@ func invalidAttrOnNonExistingParamIndex(_ ne: NE) -> NE {
ne ne
} }
@lifetime(ne, ne) // expected-error{{duplicate lifetime dependence specifier}} @lifetime(copy ne, borrow ne) // expected-error{{duplicate lifetime dependence specifier}}
func invalidDuplicateLifetimeDependence1(_ ne: borrowing NE) -> NE { func invalidDuplicateLifetimeDependence1(_ ne: borrowing NE) -> NE {
ne ne
} }
@@ -34,8 +34,8 @@ func invalidDependence(_ x: consuming Klass) -> NE {
NE() NE()
} }
@lifetime(result: source) @lifetime(result: copy source)
@lifetime(result: source) // TODO: display error here @lifetime(result: borrow source) // TODO: display error here
func invalidTarget(_ result: inout NE, _ source: consuming NE) { // expected-error{{invalid duplicate target lifetime dependencies on function}} func invalidTarget(_ result: inout NE, _ source: consuming NE) { // expected-error{{invalid duplicate target lifetime dependencies on function}}
result = source result = source
} }
@@ -62,4 +62,4 @@ do {
// rdar://146401190 ([nonescapable] implement non-inout parameter dependencies) // rdar://146401190 ([nonescapable] implement non-inout parameter dependencies)
@lifetime(span: borrow holder) @lifetime(span: borrow holder)
func testParameterDep(holder: Holder, span: Span<Int>) {} // expected-error {{lifetime-dependent parameter must be 'inout'}} func testParameterDep(holder: AnyObject, span: Span<Int>) {} // expected-error{{lifetime-dependent parameter must be 'inout'}}

View File

@@ -1,10 +1,10 @@
// RUN: %target-typecheck-verify-swift -disable-availability-checking // RUN: %target-typecheck-verify-swift -disable-availability-checking
// REQUIRES: asserts // REQUIRES: asserts
struct NE : ~Escapable { struct NE : ~Escapable { // expected-error{{an implicit initializer with a ~Escapable result requires '-enable-experimental-feature LifetimeDependence'}}
} }
@lifetime(ne) // expected-error{{'@lifetime' attribute is only valid when experimental feature LifetimeDependence is enabled}} expected-error{{expected declaration}} @lifetime(copy ne) // expected-error{{'@lifetime' attribute is only valid when experimental feature LifetimeDependence is enabled}} expected-error{{expected declaration}}
func derive(_ ne: NE) -> NE { // expected-error{{returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'}} func derive(_ ne: NE) -> NE { // expected-error{{a function with a ~Escapable result requires '-enable-experimental-feature LifetimeDependence'}}
ne ne
} }

View File

@@ -107,7 +107,7 @@ struct EscapableTrivialSelf {
mutating func mutatingMethodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a mutating method with a ~Escapable result requires '@lifetime(...)'}} mutating func mutatingMethodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a mutating method with a ~Escapable result requires '@lifetime(...)'}}
@lifetime(borrow self) @lifetime(self)
mutating func mutatingMethodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() } mutating func mutatingMethodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}} @lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}}
@@ -135,7 +135,7 @@ struct EscapableNonTrivialSelf {
func mutatingMethodNoParam() -> NEImmortal { NEImmortal() } func mutatingMethodNoParam() -> NEImmortal { NEImmortal() }
@lifetime(borrow self) @lifetime(self)
mutating func mutatingMethodNoParamLifetime() -> NEImmortal { NEImmortal() } mutating func mutatingMethodNoParamLifetime() -> NEImmortal { NEImmortal() }
@lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}} @lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}}
@@ -329,6 +329,7 @@ struct NonescapableSelfAccessors: ~Escapable {
yield ne yield ne
} }
@lifetime(borrow self)
_modify { _modify {
yield &ne yield &ne
} }
@@ -407,7 +408,7 @@ struct NonescapableSelfAccessors: ~Escapable {
} }
} }
struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { // expected-error{{cannot infer the lifetime dependence scope on an implicit initializer with a ~Escapable parameter, specify '@lifetime(borrow ne)' or '@lifetime(copy ne)'}} struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
var ne: NE var ne: NE
var neComputed: NE { var neComputed: NE {
@@ -425,6 +426,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { // expected-error{{can
yield ne yield ne
} }
@lifetime(borrow self)
_modify { _modify {
yield &ne yield &ne
} }

View File

@@ -13,14 +13,17 @@ struct NE: ~Escapable {
init() {} init() {}
} }
@lifetime(copy ne)
func transfer(_ ne: NE) -> NE { func transfer(_ ne: NE) -> NE {
ne ne
} }
@lifetime(copy ne)
func applyAnnotatedTransfer(ne: NE, @lifetime(0) transfer: (NE) -> NE) -> NE { // expected-error{{'@lifetime' attribute cannot be applied to this declaration}} func applyAnnotatedTransfer(ne: NE, @lifetime(0) transfer: (NE) -> NE) -> NE { // expected-error{{'@lifetime' attribute cannot be applied to this declaration}}
transfer(ne) transfer(ne)
} }
@lifetime(copy ne)
func applyTransfer(ne: NE, transfer: (NE) -> NE) -> NE { func applyTransfer(ne: NE, transfer: (NE) -> NE) -> NE {
transfer(ne) transfer(ne)
} }
@@ -36,6 +39,7 @@ func borrow(_ nc: borrowing NC) -> NE {
nc.ne nc.ne
} }
@lifetime(borrow nc)
func applyBorrow(nc: borrowing NC, borrow: (borrowing NC) -> NE) -> NE { func applyBorrow(nc: borrowing NC, borrow: (borrowing NC) -> NE) -> NE {
borrow(nc) borrow(nc)
} }

View File

@@ -17,11 +17,11 @@ public struct BufferView : ~Escapable {
public init(_ ptr: UnsafeRawBufferPointer, _ a: borrowing Array<Int>) { public init(_ ptr: UnsafeRawBufferPointer, _ a: borrowing Array<Int>) {
self.ptr = ptr self.ptr = ptr
} }
@lifetime(a) @lifetime(copy a)
public init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView) { public init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView) {
self.ptr = ptr self.ptr = ptr
} }
@lifetime(a, borrow b) @lifetime(copy a, borrow b)
public init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView, _ b: borrowing Array<Int>) { public init(_ ptr: UnsafeRawBufferPointer, _ a: consuming AnotherView, _ b: borrowing Array<Int>) {
self.ptr = ptr self.ptr = ptr
} }
@@ -48,12 +48,12 @@ public func borrowAndCreate(_ view: borrowing BufferView) -> BufferView {
return BufferView(view.ptr) return BufferView(view.ptr)
} }
@lifetime(view) @lifetime(copy view)
public func consumeAndCreate(_ view: consuming BufferView) -> BufferView { public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
return BufferView(view.ptr) return BufferView(view.ptr)
} }
@lifetime(borrow this, that) @lifetime(borrow this, copy that)
public func deriveThisOrThat(_ this: borrowing BufferView, _ that: borrowing BufferView) -> BufferView { public func deriveThisOrThat(_ this: borrowing BufferView, _ that: borrowing BufferView) -> BufferView {
if (Int.random(in: 1..<100) == 0) { if (Int.random(in: 1..<100) == 0) {
return BufferView(this.ptr) return BufferView(this.ptr)
@@ -63,13 +63,16 @@ public func deriveThisOrThat(_ this: borrowing BufferView, _ that: borrowing Buf
public struct Wrapper : ~Escapable { public struct Wrapper : ~Escapable {
var _view: BufferView var _view: BufferView
@lifetime(copy view)
public init(_ view: consuming BufferView) { public init(_ view: consuming BufferView) {
self._view = view self._view = view
} }
public var view: BufferView { public var view: BufferView {
@lifetime(copy self)
_read { _read {
yield _view yield _view
} }
@lifetime(borrow self)
_modify { _modify {
yield &_view yield &_view
} }

View File

@@ -7,6 +7,7 @@ public struct BufferView : ~Escapable {
self.c = c self.c = c
} }
@inlinable @inlinable
@lifetime(copy otherBV)
public init(_ otherBV: borrowing BufferView) { public init(_ otherBV: borrowing BufferView) {
self.ptr = otherBV.ptr self.ptr = otherBV.ptr
self.c = otherBV.c self.c = otherBV.c
@@ -24,14 +25,17 @@ public struct MutableBufferView : ~Escapable, ~Copyable {
} }
@inlinable @inlinable
@lifetime(copy x)
public func derive(_ x: borrowing BufferView) -> BufferView { public func derive(_ x: borrowing BufferView) -> BufferView {
return BufferView(x.ptr, x.c) return BufferView(x.ptr, x.c)
} }
@lifetime(copy view)
public func borrowAndCreate(_ view: borrowing BufferView) -> BufferView { public func borrowAndCreate(_ view: borrowing BufferView) -> BufferView {
return BufferView(view.ptr, view.c ) return BufferView(view.ptr, view.c )
} }
@lifetime(copy view)
public func consumeAndCreate(_ view: consuming BufferView) -> BufferView { public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
return BufferView(view.ptr, view.c) return BufferView(view.ptr, view.c)
} }
@@ -54,13 +58,16 @@ public struct Container : ~Copyable {
public struct Wrapper : ~Escapable { public struct Wrapper : ~Escapable {
var _view: BufferView var _view: BufferView
public var view: BufferView { public var view: BufferView {
@lifetime(copy self)
_read { _read {
yield _view yield _view
} }
@lifetime(borrow self)
_modify { _modify {
yield &_view yield &_view
} }
} }
@lifetime(copy view)
public init(_ view: consuming BufferView) { public init(_ view: consuming BufferView) {
self._view = view self._view = view
} }