Skip to content

Commit 50ee84a

Browse files
committed
Infer LifetimeDependenceInfo on a mutating method
We need this at least until we have 'dependsOn(self)' syntax. When 'self' is nonescapable and the result is 'void', assume that 'self' depends on a single nonescapable argument.
1 parent 1164046 commit 50ee84a

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

include/swift/AST/LifetimeDependence.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ class LifetimeDependenceInfo {
163163
static std::optional<LifetimeDependenceInfo>
164164
inferSetter(AbstractFunctionDecl *afd);
165165

166+
/// Infer LifetimeDependenceInfo on mutating self
167+
static std::optional<LifetimeDependenceInfo>
168+
inferMutatingSelf(AbstractFunctionDecl *afd);
169+
166170
/// Builds LifetimeDependenceInfo from SIL function type
167171
static std::optional<LifetimeDependenceInfo>
168172
fromTypeRepr(LifetimeDependentTypeRepr *lifetimeDependentRepr,

lib/AST/LifetimeDependence.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/TypeRepr.h"
2121
#include "swift/Basic/Assertions.h"
2222
#include "swift/Basic/Defer.h"
23+
#include "swift/Basic/Range.h"
2324

2425
namespace swift {
2526

@@ -444,6 +445,16 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
444445
if (accessor->getAccessorKind() == AccessorKind::Set) {
445446
return inferSetter(accessor);
446447
}
448+
} else if (auto *fd = dyn_cast<FuncDecl>(afd)) {
449+
// Infer self dependence for a mutating function with no result.
450+
//
451+
// FIXME: temporary hack until we have dependsOn(self: param) syntax.
452+
// Do not apply this to accessors (_modify). _modify is handled below like a
453+
// mutating method.
454+
if (fd->isMutating() && fd->getResultInterfaceType()->isVoid()
455+
&& !dc->getSelfTypeInContext()->isEscapable()) {
456+
return inferMutatingSelf(afd);
457+
}
447458
}
448459

449460
if (hasEscapableResultOrYield(afd)) {
@@ -487,6 +498,11 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
487498
return std::nullopt;
488499
}
489500

501+
// Infer method dependence: result depends on self.
502+
//
503+
// This includes _modify. A _modify's yielded value depends on self. The
504+
// caller of the _modify ensures that the 'self' depends on any value stored
505+
// to the yielded address.
490506
return LifetimeDependenceInfo::getForIndex(
491507
afd, resultIndex, /*selfIndex */ afd->getParameters()->size(), kind);
492508
}
@@ -551,7 +567,7 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
551567
afd, resultIndex, *candidateParamIndex, *candidateLifetimeKind);
552568
}
553569

554-
/// Infer LifetimeDependenceInfo on a setter where 'self' is nonescapable.
570+
/// Infer LifetimeDependence on a setter where 'self' is nonescapable.
555571
std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::inferSetter(
556572
AbstractFunctionDecl *afd) {
557573

test/SIL/implicit_lifetime_dependence.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public struct OuterNE: ~Escapable {
172172
// A public property generates an implicit setter with an infered dependence on 'newValue'.
173173
//
174174
// CHECK-LABEL: sil [transparent] @$s28implicit_lifetime_dependence7OuterNEV5innerAC05InnerE0Vvs : $@convention(method) (@owned OuterNE.InnerNE, _inherit(0) @inout OuterNE) -> () {
175-
public var inner1: InnerNE
175+
var inner1: InnerNE
176176

177177
// Explicit setter with an infered dependence on 'newValue'.
178178
public var inner2: InnerNE {
@@ -189,4 +189,11 @@ public struct OuterNE: ~Escapable {
189189
init<Owner: ~Copyable & ~Escapable>(owner: borrowing Owner) -> dependsOn(owner) Self {
190190
self.inner1 = InnerNE(owner: owner)
191191
}
192+
193+
// Infer a dependence from 'self' on 'value'. We might revoke this rule once we have dependsOn(self:) syntax.
194+
//
195+
// CHECK-LABEL: sil hidden [ossa] @$s28implicit_lifetime_dependence7OuterNEV8setInner5valueyAC0gE0V_tF : $@convention(method) (@guaranteed OuterNE.InnerNE, _inherit(0) @inout OuterNE) -> () {
196+
mutating func setInner(value: InnerNE) {
197+
self.inner1 = value
198+
}
192199
}

0 commit comments

Comments
 (0)