Skip to content

Commit 92b2a85

Browse files
committed
Fix LifetimeDependenceDiagnostics: handle mark_dependence_addr
A small typo meant that scoped dependencies modeled with mark_dependence_addr were not diagnosed.
1 parent a7c9b6e commit 92b2a85

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceDiagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
5353
}
5454
}
5555
for instruction in function.instructions {
56-
if let markDep = instruction as? MarkDependenceInst, markDep.isUnresolved {
56+
if let markDep = instruction as? MarkDependenceInstruction, markDep.isUnresolved {
5757
if let lifetimeDep = LifetimeDependence(markDep, context) {
5858
if analyze(dependence: lifetimeDep, context) {
5959
// Note: This promotes the mark_dependence flag but does not invalidate analyses; preserving analyses is good,

test/SILOptimizer/lifetime_dependence/verify_diagnostics.sil

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ sil @getNE : $@convention(thin) (@in_guaranteed Holder) -> @lifetime(borrow addr
5656
sil @initTrivialHolder : $@convention(thin) () -> @out TrivialHolder
5757
sil @getTrivialNE : $@convention(thin) (@in_guaranteed TrivialHolder) -> @lifetime(borrow address_for_deps 0) @owned NE
5858

59+
sil @makeHolder: $@convention(method) (@thin Holder.Type) -> @owned Holder // user: %6
60+
sil @getGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : ~Escapable> (@guaranteed Holder, @thick τ_0_0.Type) -> @lifetime(borrow 0) @out τ_0_0 // user: %12
61+
5962
// Test returning a owned dependence on a trivial value
6063
sil [ossa] @return_trivial_dependence : $@convention(thin) (@guaranteed C) -> @lifetime(borrow 0) @owned NE {
6164
entry(%0 : @guaranteed $C):
@@ -163,3 +166,34 @@ bb0:
163166
%12 = tuple ()
164167
return %12
165168
}
169+
170+
// Test a borrowed dependency on an address
171+
sil [ossa] @testBorrowAddress : $@convention(thin) <T where T : ~Escapable> (@thick T.Type) -> @lifetime(immortal) @out T {
172+
bb0(%0 : $*T, %1 : $@thick T.Type):
173+
debug_value %1, let, name "type", argno 1
174+
%3 = alloc_stack [lexical] [var_decl] $Holder, var, name "holder", type $Holder
175+
%4 = metatype $@thin Holder.Type
176+
177+
%5 = function_ref @makeHolder : $@convention(method) (@thin Holder.Type) -> @owned Holder
178+
%6 = apply %5(%4) : $@convention(method) (@thin Holder.Type) -> @owned Holder
179+
store %6 to [init] %3
180+
%8 = alloc_stack [lexical] [var_decl] $T, let, name "result"
181+
// expected-error @-1{{lifetime-dependent value escapes its scope}}
182+
%9 = begin_access [read] [static] %3
183+
// expected-note @-1{{it depends on this scoped access to variable}}
184+
%10 = load [copy] %9
185+
186+
%11 = function_ref @getGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : ~Escapable> (@guaranteed Holder, @thick τ_0_0.Type) -> @lifetime(borrow 0) @out τ_0_0
187+
%12 = apply %11<T>(%8, %10, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : ~Escapable> (@guaranteed Holder, @thick τ_0_0.Type) -> @lifetime(borrow 0) @out τ_0_0
188+
mark_dependence_addr [unresolved] %8 on %9
189+
destroy_value %10
190+
copy_addr %8 to [init] %0
191+
// expected-note @-1{{this use causes the lifetime-dependent value to escape}}
192+
end_access %9
193+
destroy_addr %8
194+
dealloc_stack %8
195+
destroy_addr %3
196+
dealloc_stack %3
197+
%21 = tuple ()
198+
return %21
199+
}

test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ struct A {}
3636

3737
func useA(_:A){}
3838

39+
struct NE : ~Escapable {}
40+
41+
class C {}
42+
struct Holder {
43+
var c: C? = nil
44+
}
45+
46+
@_silgen_name("getGeneric")
47+
@lifetime(borrow holder)
48+
func getGeneric<T: ~Escapable>(_ holder: borrowing Holder, _: T.Type) -> T
49+
50+
func mutate(_: inout Holder) {}
51+
3952
// Test that conditionally returning an Optional succeeds.
4053
//
4154
// See scope_fixup.sil: testReturnPhi.
@@ -67,3 +80,14 @@ struct TestDeinitCallsAddressor: ~Copyable, ~Escapable {
6780
useA(a[])
6881
}
6982
}
83+
84+
// Test a borrowed dependency on an address
85+
@lifetime(immortal)
86+
public func testGenericDep<T: ~Escapable>(type: T.Type) -> T {
87+
let holder = Holder()
88+
let result = getGeneric(holder, type)
89+
// expected-error @-1{{lifetime-dependent variable 'result' escapes its scope}}
90+
// expected-note @-3{{it depends on the lifetime of variable 'holder'}}
91+
return result
92+
// expected-note @-1{{this use causes the lifetime-dependent value to escape}}
93+
}

0 commit comments

Comments
 (0)