Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions lib/AST/LifetimeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,8 @@ class LifetimeDependenceChecker {
}

bool nonEscapableSelf = isDiagnosedNonEscapable(selfTypeInContext);
if (auto accessor = dyn_cast<AccessorDecl>(afd)) {
auto accessor = dyn_cast<AccessorDecl>(afd);
if (accessor) {
if (isImplicitOrSIL() || useLazyInference()) {
if (nonEscapableSelf && afd->getImplicitSelfDecl()->isInOut()) {
// Implicit accessors that return or yield a non-Escapable value may
Expand All @@ -1038,14 +1039,18 @@ class LifetimeDependenceChecker {
}
// Explicit accessors are inferred the same way as regular methods.
}
// Do infer the result of a mutating method when 'self' is
// non-Escapable. The missing dependence on inout 'self' will be diagnosed
// later anyway, so an explicit annotation will still be needed.
// Do not infer the result's dependence when the method is mutating and
// 'self' is non-Escapable. Independently, a missing dependence on inout
// 'self' will be diagnosed. Since an explicit annotation will be needed for
// 'self', we also require the method's result to have an explicit
// annotation.
if (nonEscapableSelf && afd->getImplicitSelfDecl()->isInOut()) {
return;
}
// Methods with parameters only apply to lazy inference.
if (!useLazyInference() && afd->getParameters()->size() > 0) {
// Methods with parameters only apply to lazy inference. This does not
// include accessors because a subscript's index is assumed not to be the
// source of the result's dependency.
if (!accessor && !useLazyInference() && afd->getParameters()->size() > 0) {
return;
}
if (!useLazyInference() && !isImplicitOrSIL()) {
Expand Down Expand Up @@ -1388,7 +1393,7 @@ class LifetimeDependenceChecker {
return std::nullopt;
}
if (wrappedAccessorKind) {
auto *var = cast<VarDecl>(accessor->getStorage());
auto *var = cast<AbstractStorageDecl>(accessor->getStorage());
for (auto *wrappedAccessor : var->getAllAccessors()) {
if (wrappedAccessor->isImplicit())
continue;
Expand Down
10 changes: 10 additions & 0 deletions test/Sema/lifetime_depend_infer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,16 @@ struct Accessors {
yield &ne
}
}

// Synthesized _modify...
subscript(_ index: Int) -> NEImmortal {
get { // OK
NEImmortal()
}

set { // OK (no dependency)
}
}
}

struct TrivialAccessors {
Expand Down