Skip to content

Commit a9b489c

Browse files
authored
Merge pull request #71697 from meg-gupta/enableinference
Enable lifetime dependence inference when NonescapableTypes is on
2 parents 0b37768 + ca73cba commit a9b489c

11 files changed

+59
-10
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7845,6 +7845,10 @@ ERROR(lifetime_dependence_cannot_use_infer, none,
78457845
(StringRef))
78467846
ERROR(lifetime_dependence_on_bitwise_copyable, none,
78477847
"invalid lifetime dependence on bitwise copyable type", ())
7848+
ERROR(lifetime_dependence_cannot_infer_implicit_init, none,
7849+
"cannot infer lifetime dependence on implicit initializer of ~Escapable"
7850+
" type, define an initializer with explicit lifetime dependence"
7851+
" specifiers", ())
78487852

78497853
//===----------------------------------------------------------------------===//
78507854
// MARK: Transferring

include/swift/Basic/LangOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ namespace swift {
563563
bool EnableExperimentalAssociatedTypeInference = false;
564564

565565
/// Enable implicit lifetime dependence for ~Escapable return types.
566-
bool EnableExperimentalLifetimeDependenceInference = false;
566+
bool EnableExperimentalLifetimeDependenceInference = true;
567567

568568
/// Enables dumping type witness systems from associated type inference.
569569
bool DumpTypeWitnessSystems = false;

lib/Sema/LifetimeDependence.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
317317
ownership);
318318
}
319319

320+
auto *cd = dyn_cast<ConstructorDecl>(afd);
321+
if (cd && cd->isImplicit() && cd->getParameters()->size() == 0) {
322+
return std::nullopt;
323+
}
324+
320325
LifetimeDependenceInfo lifetimeDependenceInfo;
321326
ParamDecl *candidateParam = nullptr;
322327
unsigned paramIndex = 0;
@@ -349,6 +354,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) {
349354

350355
paramIndex++;
351356
}
357+
if (cd && cd->isImplicit()) {
358+
diags.diagnose(cd->getLoc(),
359+
diag::lifetime_dependence_cannot_infer_implicit_init);
360+
return std::nullopt;
361+
}
352362
if (!candidateParam && !hasParamError) {
353363
diags.diagnose(returnLoc,
354364
diag::lifetime_dependence_cannot_infer_no_candidates);

test/Generics/inverse_extension_signatures.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@
6363
// CHECK-NEXT: (normal_conformance type="Outer<A>" protocol="Copyable"
6464
// CHECK-NEXT: (requirement "A" conforms_to "Copyable"))
6565

66-
// CHECK-LABEL: ExtensionDecl line=0 base=Freestanding<T>
67-
// CHECK-NEXT: (normal_conformance type="Freestanding<T>" protocol="Copyable"
68-
// CHECK-NEXT: (requirement "T" conforms_to "Copyable"))
69-
7066
// CHECK-LABEL: ExtensionDecl line=0 base=Freestanding<T>
7167
// CHECK-NEXT: (normal_conformance type="Freestanding<T>" protocol="Escapable"
7268
// CHECK-NEXT: (requirement "T" conforms_to "Escapable"))
7369

70+
// CHECK-LABEL: ExtensionDecl line=0 base=Freestanding<T>
71+
// CHECK-NEXT: (normal_conformance type="Freestanding<T>" protocol="Copyable"
72+
// CHECK-NEXT: (requirement "T" conforms_to "Copyable"))
73+
7474
public struct Outer<A: ~Copyable> {
7575
public func innerFn<B: ~Copyable>(_ b: borrowing B) {}
7676
public struct InnerStruct<C: ~Copyable> {

test/Generics/inverse_generics.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,16 @@ struct NonescapingType: ~Escapable {}
266266

267267
struct Wraps: ~Escapable {
268268
let x: MaybeEscapes<NonescapingType>
269+
init(_ x: consuming MaybeEscapes<NonescapingType>) {
270+
self.x = x
271+
}
269272
}
270273

271274
struct NonescapeDoesNotAllowNoncopyable: ~Escapable { // expected-note {{consider adding '~Copyable' to struct 'NonescapeDoesNotAllowNoncopyable'}}
272275
let x: NC // expected-error {{stored property 'x' of 'Copyable'-conforming struct 'NonescapeDoesNotAllowNoncopyable' has non-Copyable type 'NC'}}
276+
init(_ x: borrowing NC) {
277+
self.x = x
278+
}
273279
}
274280

275281
enum MaybeEscapes<T: ~Escapable> { // expected-note {{generic enum 'MaybeEscapes' has '~Escapable' constraint on a generic parameter, making its 'Escapable' conformance conditional}}

test/ModuleInterface/noncopyable_generics.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ import NoncopyableGenerics_Misc
123123
// Synthesized conditional conformances are next
124124

125125
// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics
126-
// CHECK-MISC-NEXT: extension {{.*}}.Hello : Swift.Copyable where T : ~Escapable {
126+
// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Escapable where T : ~Copyable {
127+
// CHECK-MISC-NEXT: }
128+
// CHECK-MISC-NEXT: #endif
129+
// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics
130+
// CHECK-MISC-NEXT: extension NoncopyableGenerics_Misc.Hello : Swift.Copyable where T : ~Escapable {
131+
// CHECK-MISC-NEXT: }
132+
// CHECK-MISC-NEXT: #endif
127133

128134
// FIXME: (rdar://123293620) inner struct extensions are not feature-guarded correctly
129135
// CHECK-MISC: extension {{.*}}.Outer.InnerStruct : Swift.Copyable {
@@ -132,10 +138,10 @@ import NoncopyableGenerics_Misc
132138
// CHECK-MISC: extension {{.*}}.Outer : Swift.Copyable {
133139

134140
// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics
135-
// CHECK-MISC-NEXT: extension {{.*}}.Freestanding : Swift.Copyable where T : ~Escapable {
141+
// CHECK-MISC-NEXT: extension {{.*}}.Freestanding : Swift.Escapable where T : ~Copyable {
136142

137143
// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics
138-
// CHECK-MISC-NEXT: extension {{.*}}.Freestanding : Swift.Escapable where T : ~Copyable {
144+
// CHECK-MISC-NEXT: extension {{.*}}.Freestanding : Swift.Copyable where T : ~Escapable {
139145

140146
////////////////////////////////////////////////////////////////////////
141147
// At the end, ensure there are no synthesized Copyable extensions

test/SIL/Parser/basic2_noncopyable_generics.sil

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ struct NCG<T> : ~Copyable {
2626
deinit
2727
}
2828

29-
// CHECK-LABEL: struct NEG<T> : ~Escapable {
29+
// CHECK-LABEL: struct NEG<T> : ~Escapable where T : ~Escapable {
3030
// CHECK-NEXT: var t: T
31-
struct NEG<T> : ~Escapable {
31+
struct NEG<T : ~Escapable> : ~Escapable {
3232
var t: T
33+
init(_ t: consuming T) {
34+
self.t = t
35+
}
3336
}

test/SILOptimizer/lifetime_dependence_borrow.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ struct BV {
2828
struct NCNE : ~Copyable {
2929
let p: UnsafeRawPointer
3030
let c: Int
31+
32+
@_unsafeNonescapableResult
33+
init(_ p: UnsafeRawPointer, _ c: Int) {
34+
self.p = p
35+
self.c = c
36+
}
3137

3238
// Requires a borrow.
3339
borrowing func getBV() -> _borrow(self) BV {

test/SILOptimizer/lifetime_dependence_diagnostics.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
struct BV {
1414
let p: UnsafeRawPointer
1515
let c: Int
16+
@_unsafeNonescapableResult
17+
init(_ p: UnsafeRawPointer, _ c: Int) {
18+
self.p = p
19+
self.c = c
20+
}
1621
}
1722

1823
func bv_copy(_ bv: borrowing BV) -> _copy(bv) BV {

test/SILOptimizer/lifetime_dependence_util.sil

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ sil_vtable D {
3939
@_nonescapable
4040
struct NE {
4141
var d: D
42+
@_unsafeNonescapableResult
43+
init() { }
4244
}
4345

4446
@_nonescapable
4547
struct NEWrap {
4648
var ne: NE
49+
@_unsafeNonescapableResult
50+
init() { }
4751
}
4852

4953
sil @coroutine : $@yield_once @convention(method) (@guaranteed NE) -> @yields @guaranteed NE

test/Sema/explicit_lifetime_dependence_specifiers.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct Container {
88

99
struct BufferView : ~Escapable {
1010
let ptr: UnsafeRawBufferPointer
11+
@_unsafeNonescapableResult
1112
init(_ ptr: UnsafeRawBufferPointer) {
1213
self.ptr = ptr
1314
}
@@ -19,6 +20,7 @@ struct BufferView : ~Escapable {
1920

2021
struct MutableBufferView : ~Escapable, ~Copyable {
2122
let ptr: UnsafeMutableRawBufferPointer
23+
@_unsafeNonescapableResult
2224
init(_ ptr: UnsafeMutableRawBufferPointer) {
2325
self.ptr = ptr
2426
}
@@ -97,6 +99,9 @@ func invalidSpecifierPosition2(_ x: borrowing BufferView) -> BufferView {
9799

98100
struct Wrapper : ~Escapable {
99101
let view: BufferView
102+
init(_ view: consuming BufferView) {
103+
self.view = view
104+
}
100105
borrowing func getView1() -> _borrow(self) BufferView {
101106
return view
102107
}

0 commit comments

Comments
 (0)