Skip to content

Commit 222ee73

Browse files
committed
Diagnose @_lifetime on targets that are Escapable
Lifetime dependencies can be attached to ~Escapable types only
1 parent 3a28941 commit 222ee73

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8334,6 +8334,8 @@ ERROR(lifetime_dependence_duplicate_target, none,
83348334
"invalid duplicate target lifetime dependencies on function", ())
83358335
ERROR(lifetime_parameter_requires_inout, none,
83368336
"lifetime-dependent parameter '%0' must be 'inout'", (StringRef))
8337+
ERROR(lifetime_target_requires_nonescapable, none,
8338+
"invalid lifetime dependence on an Escapable %0", (StringRef))
83378339

83388340
//------------------------------------------------------------------------------
83398341
// MARK: Lifetime Dependence Requirements

lib/AST/LifetimeDependence.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@ static bool isDiagnosedNonEscapable(Type type) {
227227
return !type->isEscapable();
228228
}
229229

230+
static bool isDiagnosedEscapable(Type type) {
231+
if (type->hasError()) {
232+
return false;
233+
}
234+
return type->isEscapable();
235+
}
236+
230237
void LifetimeDependenceInfo::getConcatenatedData(
231238
SmallVectorImpl<bool> &concatenatedData) const {
232239
auto pushData = [&](IndexSubset *paramIndices) {
@@ -893,8 +900,16 @@ class LifetimeDependenceChecker {
893900
diag::lifetime_parameter_requires_inout,
894901
targetDescriptor->getString());
895902
}
903+
if (isDiagnosedEscapable(targetDeclAndIndex->first->getTypeInContext())) {
904+
diagnose(targetDescriptor->getLoc(),
905+
diag::lifetime_target_requires_nonescapable, "target");
906+
}
896907
targetIndex = targetDeclAndIndex->second;
897908
} else {
909+
if (isDiagnosedEscapable(getResultOrYield())) {
910+
diagnose(entry->getLoc(), diag::lifetime_target_requires_nonescapable,
911+
"result");
912+
}
898913
targetIndex = afd->hasImplicitSelfDecl()
899914
? afd->getParameters()->size() + 1
900915
: afd->getParameters()->size();

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,6 @@ public func expectNil<T>(
754754
}
755755
}
756756

757-
@_lifetime(copy value)
758757
public func expectNil<T: ~Copyable & ~Escapable>(
759758
_ value: borrowing T?,
760759
_ message: @autoclosure () -> String = "",

test/Sema/lifetime_attr.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,33 @@ struct Wrapper : ~Escapable {
142142
}
143143
}
144144

145+
@_lifetime(inValue) // expected-error{{invalid lifetime dependence on an Escapable result}}
146+
func getInt(_ inValue: Int) -> Int {
147+
return inValue
148+
}
149+
150+
@_lifetime(_outValue: borrow inValue) // expected-error{{invalid lifetime dependence on an Escapable target}}
151+
func getInt(_outValue: inout Int, _ inValue: Int) {
152+
_outValue = inValue
153+
}
154+
155+
@_lifetime(inValue) // expected-error{{invalid lifetime dependence on an Escapable result}}
156+
func getGeneric<T>(_ inValue: T) -> T {
157+
return inValue
158+
}
159+
160+
@_lifetime(_outValue: borrow inValue) // expected-error{{invalid lifetime dependence on an Escapable target}}
161+
func getGeneric<T>(_outValue: inout T, _ inValue: T) {
162+
_outValue = inValue
163+
}
164+
165+
@_lifetime(borrow inValue)
166+
func getGeneric<T : ~Escapable>(_ inValue: T) -> T {
167+
return inValue
168+
}
169+
170+
@_lifetime(_outValue: borrow inValue)
171+
func getGeneric<T : ~Escapable>(_outValue: inout T, _ inValue: T) {
172+
_outValue = inValue
173+
}
174+

0 commit comments

Comments
 (0)