Skip to content

Commit c05ddd6

Browse files
committed
Fix lifetime_dependence tests for trivial dependence.
To allow enforcement of trivial borrows.
1 parent 3897929 commit c05ddd6

File tree

6 files changed

+48
-15
lines changed

6 files changed

+48
-15
lines changed

test/SIL/implicit_lifetime_dependence.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
// REQUIRES: swift_feature_LifetimeDependence
88
// REQUIRES: swift_feature_LifetimeDependenceDiagnoseTrivial
99

10+
@_unsafeNonescapableResult
11+
@lifetime(source)
12+
func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
13+
dependent: consuming T, dependsOn source: borrowing U)
14+
-> T {
15+
dependent
16+
}
17+
1018
struct BufferView : ~Escapable {
1119
let ptr: UnsafeRawBufferPointer
1220
let c: Int
@@ -136,6 +144,7 @@ struct GenericBufferView<Element> : ~Escapable {
136144
let count: Int
137145

138146
// CHECK-LABEL: sil hidden @$s28implicit_lifetime_dependence17GenericBufferViewV11baseAddress5countACyxGSV_SitcfC : $@convention(method) <Element> (UnsafeRawPointer, Int, @thin GenericBufferView<Element>.Type) -> @lifetime(borrow 0) @owned GenericBufferView<Element> {
147+
@lifetime(borrow baseAddress)
139148
init<Storage>(baseAddress: Pointer,
140149
count: Int,
141150
dependsOn: borrowing Storage) {
@@ -162,10 +171,13 @@ struct GenericBufferView<Element> : ~Escapable {
162171
// CHECK: sil hidden @$s28implicit_lifetime_dependence17GenericBufferViewVyACyxGAA9FakeRangeVySVGcig : $@convention(method) <Element> (FakeRange<UnsafeRawPointer>, @guaranteed GenericBufferView<Element>) -> @lifetime(copy 1) @owned GenericBufferView<Element> {
163172
subscript(bounds: FakeRange<Pointer>) -> Self {
164173
get {
165-
GenericBufferView(
166-
baseAddress: UnsafeRawPointer(bounds.lowerBound),
174+
let pointer = UnsafeRawPointer(bounds.lowerBound)
175+
let result = GenericBufferView(
176+
baseAddress: pointer,
167177
count: bounds.upperBound.distance(to:bounds.lowerBound) / MemoryLayout<Element>.stride
168178
)
179+
// assuming that bounds is within self
180+
return unsafeLifetime(dependent: result, dependsOn: self)
169181
}
170182
}
171183
}

test/SILOptimizer/lifetime_dependence/lifetime_dependence_insertion.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ func bv_borrow_var(p: UnsafeRawPointer, i: Int) {
5858
// CHECK: apply %{{.*}}<UnsafePointer<Int>, UnsafeRawPointer>([[RAW:%.*]], %{{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
5959
// CHECK: [[RAW:%.*]] = load [trivial] %6 : $*UnsafeRawPointer
6060
// CHECK: [[BV:%.*]] = apply %13([[RAW]], {{.*}}) : $@convention(method) (UnsafeRawPointer, Int, @thin BV.Type) -> @lifetime(borrow 0) @owned BV
61-
// CHECK: return [[BV]] : $BV
61+
// CHECK: [[MD:%.*]] = mark_dependence [unresolved] [[BV]] : $BV on %0 : $UnsafePointer<Int>
62+
// CHECK: return [[MD]] : $BV
6263
// CHECK-LABEL: } // end sil function '$s4test18bv_pointer_convert1pAA2BVVSPySiG_tF'
6364
@lifetime(borrow p)
6465
func bv_pointer_convert(p: UnsafePointer<Int>) -> BV {

test/SILOptimizer/lifetime_dependence/lifetime_dependence_mutate.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: -o /dev/null \
33
// RUN: -verify \
44
// RUN: -sil-verify-all \
5+
// RUN: -disable-access-control \
56
// RUN: -module-name test \
67
// RUN: -enable-experimental-feature LifetimeDependence \
78
// RUN: -enable-experimental-feature LifetimeDependenceDiagnoseTrivial
@@ -59,7 +60,8 @@ extension Array where Element == Int {
5960
mutating func mutspan() -> /* dependsOn(scoped self) */ MutableSpan {
6061
/* not the real implementation */
6162
let p = self.withUnsafeMutableBufferPointer { $0.baseAddress! }
62-
return MutableSpan(p, count)
63+
let span = MutableSpan(p, count)
64+
return _overrideLifetime(span, borrowing: self)
6365
}
6466
}
6567

test/SILOptimizer/lifetime_dependence/lifetime_dependence_scope_fixup.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,15 @@ func test6(_ a: Array<Int>) {
159159
// CHECK-LABEL: sil hidden @$s31lifetime_dependence_scope_fixup5test7yySWF : $@convention(thin) (UnsafeRawBufferPointer) -> () {
160160
// CHECK: [[CONT:%.*]] = alloc_stack [var_decl] $View
161161
// function_ref View.init(_:_:)
162-
// CHECK: [[VIEW1:%.*]] = apply %{{.*}}(%0, %{{.*}}, %{{.*}}) : $@convention(method) (UnsafeRawBufferPointer, Int, @thin View.Type) -> @lifetime(borrow 0) @owned View // users: %14, %9, %12, %8
162+
// CHECK: [[VIEW1:%.*]] = apply %{{.*}}(%0, %{{.*}}, %{{.*}}) : $@convention(method) (UnsafeRawBufferPointer, Int, @thin View.Type) -> @lifetime(borrow 0) @owned View
163+
// CHECK: [[MD1:%.*]] = mark_dependence [nonescaping] %{{.*}} : $View on %0 : $UnsafeRawBufferPointer
163164
// CHECK: [[BA:%.*]] = begin_access [read] [static] [[CONT]] : $*View
164165
// CHECK: [[FUNC:%.*]] = function_ref @$s31lifetime_dependence_scope_fixup16getBorrowingViewyAA0G0VADF : $@convention(thin) (@guaranteed View) -> @lifetime(borrow 0) @owned View
165-
// CHECK: [[VIEW2:%.*]] = apply [[FUNC]]([[VIEW1]]) : $@convention(thin) (@guaranteed View) -> @lifetime(borrow 0) @owned View
166-
// CHECK: [[MDI:%.*]] = mark_dependence [nonescaping] [[VIEW2]] : $View on [[BA]] : $*View
166+
// CHECK: [[VIEW2:%.*]] = apply [[FUNC]]([[MD1]]) : $@convention(thin) (@guaranteed View) -> @lifetime(borrow 0) @owned View
167+
// CHECK: [[MD2:%.*]] = mark_dependence [nonescaping] [[VIEW2]] : $View on [[BA]] : $*View
167168
// CHECK: [[USE:%.*]] = function_ref @$s31lifetime_dependence_scope_fixup3useyyAA4ViewVF : $@convention(thin) (@guaranteed View) -> ()
168-
// CHECK: apply [[USE]]([[MDI]]) : $@convention(thin) (@guaranteed View) -> ()
169-
// CHECK: release_value [[MDI]] : $View
169+
// CHECK: apply [[USE]]([[MD2]]) : $@convention(thin) (@guaranteed View) -> ()
170+
// CHECK: release_value [[MD2]] : $View
170171
// CHECK: end_access [[BA]] : $*View
171172
// CHECK-LABEL: } // end sil function '$s31lifetime_dependence_scope_fixup5test7yySWF'
172173
func test7(_ a: UnsafeRawBufferPointer) {

test/SILOptimizer/lifetime_dependence/lifetime_dependence_util.sil

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,10 @@ entry(%0 : @owned $C, %1 : @owned $D, %2 : @guaranteed $D, %3 : $*D, %4 : $*D):
133133
%trivial_mark = mark_dependence [nonescaping] %yield_mark : $C on %zero : $Builtin.Int1
134134
specify_test "lifetime_dependence_scope %trivial_mark"
135135
// CHECK-LABEL: dependence_scope: lifetime_dependence_scope with: %trivial_mark
136-
// CHECK-NEXT: Trivial Dependence
136+
// CHECK-NEXT: Unknown: %{{.*}} = integer_literal $Builtin.Int1, 0
137+
// CHECK-NEXT: Dependent: %{{.*}} = mark_dependence [nonescaping]
138+
// CHECK-NEXT: begin: %{{.*}} = integer_literal $Builtin.Int1, 0
139+
// CHECK-NEXT: ends:{{[ ]+$}}
137140
// CHECK: dependence_scope: lifetime_dependence_scope with: %trivial_mark
138141

139142
%f = ref_element_addr %borrow : $D, #D.object

test/SILOptimizer/lifetime_dependence/semantics.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// REQUIRES: swift_feature_LifetimeDependenceDiagnoseTrivial
1212

1313
// Lifetime dependence semantics by example.
14-
1514
struct Span<T>: ~Escapable {
1615
private var base: UnsafePointer<T>
1716
private var count: Int
@@ -31,7 +30,8 @@ struct Span<T>: ~Escapable {
3130

3231
extension Span {
3332
consuming func dropFirst() -> Span<T> {
34-
let local = Span(base: self.base + 1, count: self.count - 1)
33+
let nextPointer = self.base + 1
34+
let local = Span(base: nextPointer, count: self.count - 1)
3535
return unsafeLifetime(dependent: local, dependsOn: self)
3636
}
3737
}
@@ -67,11 +67,12 @@ extension Span {
6767
}
6868

6969
extension Array {
70-
// TODO: comment out
71-
borrowing func span() -> /* */ Span<Element> {
70+
@lifetime(borrow self)
71+
borrowing func span() -> Span<Element> {
7272
/* not the real implementation */
7373
let p = self.withUnsafeBufferPointer { $0.baseAddress! }
74-
return Span(base: p, count: 1)
74+
let span = Span(base: p, count: 1)
75+
return unsafeLifetime(dependent: span, scope: self)
7576
}
7677
}
7778

@@ -160,3 +161,16 @@ func testScopedOfInheritedWithLet(_ arg: [Int] ) {
160161
// expected-note @-1{{it depends on the lifetime of this parent value}}
161162
_ = result
162163
} // expected-note {{this use of the lifetime-dependent value is out of scope}}
164+
165+
// =============================================================================
166+
// Scoped dependence on trivial values
167+
// =============================================================================
168+
169+
@lifetime(borrow a)
170+
func testTrivialScope<T>(a: Array<T>) -> Span<T> {
171+
let p = a.withUnsafeBufferPointer { $0.baseAddress! }
172+
return Span(base: p, count: 1)
173+
// expected-error @-1{{lifetime-dependent value escapes its scope}}
174+
// expected-note @-3{{it depends on the lifetime of variable 'p'}}
175+
// expected-note @-3{{this use causes the lifetime-dependent value to escape}}
176+
}

0 commit comments

Comments
 (0)