Skip to content

Commit 23d1329

Browse files
authored
Merge pull request #75580 from atrick/fix-lifeutil-assert
Fix an assert in LifetimeDependenceUtils to allow all valid cases.
2 parents 4c3fa03 + 3e98d2e commit 23d1329

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,8 @@ struct LifetimeDependence : CustomStringConvertible {
153153
precondition(initialAddress is AllocStackInst
154154
|| initialAddress is FunctionArgument,
155155
"expected storage for a a local 'let'")
156-
precondition(initializingStore is StoringInstruction
157-
|| initializingStore is SourceDestAddrInstruction
158-
|| initializingStore is FullApplySite,
156+
precondition(initializingStore == nil || initializingStore is StoringInstruction
157+
|| initializingStore is SourceDestAddrInstruction || initializingStore is FullApplySite,
159158
"expected a store")
160159
}
161160
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-sil \
2+
// RUN: -o /dev/null \
3+
// RUN: -verify \
4+
// RUN: -sil-verify-all \
5+
// RUN: -module-name test \
6+
// RUN: -enable-experimental-feature NonescapableTypes
7+
8+
// REQUIRES: asserts
9+
// REQUIRES: swift_in_compiler
10+
11+
// REQUIRES: rdar132874319
12+
// ([nonescapable] improve diagnostics for spanofspans.swift; prefer an exclusivity violation to a lifetime error)
13+
14+
// TODO: uncomment the @lifetime annotations when we have component lifetimes.
15+
16+
// @lifetime(elements)
17+
struct Span<T: ~Escapable>: ~Escapable {
18+
// Pretend that 'element' is in separate storage.
19+
var element: T
20+
21+
// @lifetime(elements: t)
22+
init(t: T) {
23+
self.element = t
24+
}
25+
}
26+
27+
// @lifetime(elements)
28+
extension Array {
29+
// @lifetime(span: borrow self)
30+
// @lifetime(span.elements: copy self.elements)
31+
var span: Span<Element> {
32+
_read {
33+
yield Span(t: first!)
34+
}
35+
}
36+
}
37+
38+
// use 'scalars' instead of 'elements' to avoid confusion from nesting
39+
// @lifetime(scalars)
40+
struct Vec<T: ~Escapable>: ~Escapable {
41+
// Pretend that 't' is in separate storage.
42+
var scalar: T
43+
44+
// @lifetime(scalars: t)
45+
init(t: T) {
46+
self.scalar = t
47+
}
48+
49+
// @lifetime(span: self)
50+
// @lifetime(span.elements: self.scalars)
51+
public var span: Span<T> { // expected-note {{it depends on the lifetime of argument 'self'}}
52+
_read {
53+
yield Span(t: scalar)
54+
}
55+
}
56+
}
57+
58+
func useSpan<T>(_: Span<T>) {}
59+
60+
func withFatlifetimes() {
61+
let arr = [1,2,3] // expected-note {{it depends on the lifetime of variable 'arr'}}
62+
// span depends on arr
63+
let span = arr.span
64+
// vec depends on arr
65+
var vec = Vec(t: span) // expected-error {{lifetime-dependent value escapes its scope}}
66+
// expected-note @-3{{it depends on the lifetime of variable 'arr'}}
67+
// expected-note @-1{{this use causes the lifetime-dependent value to escape}}
68+
// spanOfSpans depends on borrow vec
69+
let spanOfSpans = vec.span
70+
// firstSpan depends on spanOfSpans
71+
let firstSpan = spanOfSpans.element
72+
// 🛑 ERROR: vec mutation during borrow
73+
vec.scalar = arr.span // expected-error {{lifetime-dependent value escapes its scope}}
74+
// expected-note {{this use causes the lifetime-dependent value to escape}}
75+
// (firstSpan depends on vec)
76+
useSpan(firstSpan)
77+
// end borrow vec
78+
}

0 commit comments

Comments
 (0)