Skip to content

Commit 3e359e4

Browse files
committed
Support lifetime dependence inference on enum elements
1 parent 8e5a047 commit 3e359e4

File tree

6 files changed

+105
-21
lines changed

6 files changed

+105
-21
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8780,7 +8780,8 @@ class EnumCaseDecl final : public Decl,
87808780
/// EnumCaseDecl.
87818781
class EnumElementDecl : public DeclContext, public ValueDecl {
87828782
friend class EnumRawValuesRequest;
8783-
8783+
friend class LifetimeDependenceInfoRequest;
8784+
87848785
/// This is the type specified with the enum element, for
87858786
/// example 'Int' in 'case Y(Int)'. This is null if there is no type
87868787
/// associated with this element, as in 'case Z' or in all elements of enum
@@ -8792,6 +8793,11 @@ class EnumElementDecl : public DeclContext, public ValueDecl {
87928793
/// The raw value literal for the enum element, or null.
87938794
LiteralExpr *RawValueExpr;
87948795

8796+
protected:
8797+
struct {
8798+
unsigned NoLifetimeDependenceInfo : 1;
8799+
} LazySemanticInfo = {};
8800+
87958801
public:
87968802
EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name,
87978803
ParameterList *Params,

include/swift/AST/LifetimeDependence.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,7 @@ class LifetimeDependenceInfo {
328328
/// Builds LifetimeDependenceInfo from a swift decl, either from the explicit
329329
/// lifetime dependence specifiers or by inference based on types and
330330
/// ownership modifiers.
331-
static std::optional<ArrayRef<LifetimeDependenceInfo>>
332-
get(AbstractFunctionDecl *decl);
331+
static std::optional<ArrayRef<LifetimeDependenceInfo>> get(ValueDecl *decl);
333332

334333
/// Builds LifetimeDependenceInfo from SIL
335334
static std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5095,8 +5095,7 @@ class ImportDeclRequest
50955095
class LifetimeDependenceInfoRequest
50965096
: public SimpleRequest<
50975097
LifetimeDependenceInfoRequest,
5098-
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>(
5099-
AbstractFunctionDecl *),
5098+
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>(ValueDecl *),
51005099
RequestFlags::SeparatelyCached | RequestFlags::SplitCached> {
51015100
public:
51025101
using SimpleRequest::SimpleRequest;
@@ -5105,7 +5104,7 @@ class LifetimeDependenceInfoRequest
51055104
friend SimpleRequest;
51065105

51075106
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
5108-
evaluate(Evaluator &evaluator, AbstractFunctionDecl *AFD) const;
5107+
evaluate(Evaluator &evaluator, ValueDecl *AFD) const;
51095108

51105109
public:
51115110
// Separate caching.

lib/AST/LifetimeDependence.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ class LifetimeDependenceChecker {
286286
}
287287
}
288288

289+
LifetimeDependenceChecker(EnumElementDecl *eed)
290+
: decl(eed), dc(eed->getDeclContext()), ctx(dc->getASTContext()) {
291+
auto *paramList = eed->getParameterList();
292+
resultIndex = paramList ? eed->getParameterList()->size() + 1 : 1;
293+
}
294+
289295
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
290296
currentDependencies() const {
291297
if (lifetimeDependencies.empty()) {
@@ -351,6 +357,45 @@ class LifetimeDependenceChecker {
351357
return currentDependencies();
352358
}
353359

360+
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>> checkEnumElementDecl() {
361+
auto *eed = cast<EnumElementDecl>(decl);
362+
auto enumType = eed->getParentEnum()->mapTypeIntoContext(
363+
eed->getParentEnum()->getDeclaredInterfaceType());
364+
// Escapable enum, bailout.
365+
if (!isDiagnosedNonEscapable(enumType)) {
366+
return std::nullopt;
367+
}
368+
auto *params = eed->getParameterList();
369+
// No payload, bailout.
370+
if (!params) {
371+
return std::nullopt;
372+
}
373+
374+
auto resultIndex = params->size() + /*selfType*/ 1;
375+
auto capacity = resultIndex + 1;
376+
SmallBitVector inheritIndices(capacity);
377+
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
378+
379+
// Add all indices of ~Escapable parameters as lifetime dependence sources.
380+
for (size_t i = 0; i < params->size(); i++) {
381+
auto paramType = params->get(i)->getTypeInContext();
382+
if (!isDiagnosedNonEscapable(paramType)) {
383+
continue;
384+
}
385+
inheritIndices.set(i);
386+
}
387+
if (inheritIndices.none()) {
388+
return std::nullopt;
389+
}
390+
auto lifetimeDependenceInfo = LifetimeDependenceInfo(
391+
IndexSubset::get(eed->getASTContext(), inheritIndices), nullptr,
392+
resultIndex,
393+
/*isImmortal*/ false);
394+
lifetimeDependencies.push_back(lifetimeDependenceInfo);
395+
396+
return eed->getASTContext().AllocateCopy(lifetimeDependencies);
397+
}
398+
354399
protected:
355400
template<typename ...ArgTypes>
356401
InFlightDiagnostic diagnose(
@@ -1334,8 +1379,12 @@ class LifetimeDependenceChecker {
13341379
};
13351380

13361381
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
1337-
LifetimeDependenceInfo::get(AbstractFunctionDecl *afd) {
1338-
return LifetimeDependenceChecker(afd).checkFuncDecl();
1382+
LifetimeDependenceInfo::get(ValueDecl *decl) {
1383+
if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
1384+
return LifetimeDependenceChecker(afd).checkFuncDecl();
1385+
}
1386+
auto *eed = cast<EnumElementDecl>(decl);
1387+
return LifetimeDependenceChecker(eed).checkEnumElementDecl();
13391388
}
13401389

13411390
// This implements the logic for SIL type descriptors similar to source-level

lib/AST/TypeCheckRequests.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,24 +2738,36 @@ void ExpandBodyMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
27382738

27392739
std::optional<std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>>
27402740
LifetimeDependenceInfoRequest::getCachedResult() const {
2741-
auto *func = std::get<0>(getStorage());
2741+
auto *decl = std::get<0>(getStorage());
2742+
bool noLifetimeDependenceInfo;
27422743

2743-
if (func->LazySemanticInfo.NoLifetimeDependenceInfo)
2744+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
2745+
noLifetimeDependenceInfo = func->LazySemanticInfo.NoLifetimeDependenceInfo;
2746+
} else {
2747+
auto *eed = cast<EnumElementDecl>(decl);
2748+
noLifetimeDependenceInfo = eed->LazySemanticInfo.NoLifetimeDependenceInfo;
2749+
}
2750+
2751+
if (noLifetimeDependenceInfo)
27442752
return std::optional(std::optional<LifetimeDependenceInfo>());
27452753

2746-
return func->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
2754+
return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
27472755
}
27482756

27492757
void LifetimeDependenceInfoRequest::cacheResult(
27502758
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>> result) const {
2751-
auto *func = std::get<0>(getStorage());
2752-
2759+
auto *decl = std::get<0>(getStorage());
2760+
27532761
if (!result) {
2754-
func->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
2755-
return;
2762+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
2763+
func->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
2764+
return;
2765+
}
2766+
auto *eed = cast<EnumElementDecl>(decl);
2767+
eed->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
27562768
}
27572769

2758-
func->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
2770+
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
27592771
}
27602772

27612773
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckDecl.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,6 +2409,13 @@ static void maybeAddParameterIsolation(AnyFunctionType::ExtInfoBuilder &infoBuil
24092409
infoBuilder = infoBuilder.withIsolation(FunctionTypeIsolation::forParameter());
24102410
}
24112411

2412+
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
2413+
getLifetimeDependencies(ASTContext &context, EnumElementDecl *enumElemDecl) {
2414+
return evaluateOrDefault(context.evaluator,
2415+
LifetimeDependenceInfoRequest{enumElemDecl},
2416+
std::nullopt);
2417+
}
2418+
24122419
Type
24132420
InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
24142421
auto &Context = D->getASTContext();
@@ -2698,13 +2705,25 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
26982705
resultTy = FunctionType::get(argTy, resultTy, info);
26992706
}
27002707

2708+
auto lifetimeDependenceInfo = getLifetimeDependencies(Context, EED);
2709+
27012710
// FIXME: Verify ExtInfo state is correct, not working by accident.
27022711
if (auto genericSig = ED->getGenericSignature()) {
2703-
GenericFunctionType::ExtInfo info;
2704-
resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy, info);
2712+
GenericFunctionType::ExtInfoBuilder infoBuilder;
2713+
if (lifetimeDependenceInfo.has_value()) {
2714+
infoBuilder =
2715+
infoBuilder.withLifetimeDependencies(*lifetimeDependenceInfo);
2716+
}
2717+
resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy,
2718+
infoBuilder.build());
2719+
27052720
} else {
2706-
FunctionType::ExtInfo info;
2707-
resultTy = FunctionType::get({selfTy}, resultTy, info);
2721+
FunctionType::ExtInfoBuilder infoBuilder;
2722+
if (lifetimeDependenceInfo.has_value()) {
2723+
infoBuilder =
2724+
infoBuilder.withLifetimeDependencies(*lifetimeDependenceInfo);
2725+
}
2726+
resultTy = FunctionType::get({selfTy}, resultTy, infoBuilder.build());
27082727
}
27092728

27102729
return resultTy;
@@ -3153,7 +3172,7 @@ ImplicitKnownProtocolConformanceRequest::evaluate(Evaluator &evaluator,
31533172

31543173
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
31553174
LifetimeDependenceInfoRequest::evaluate(Evaluator &evaluator,
3156-
AbstractFunctionDecl *decl) const {
3175+
ValueDecl *decl) const {
31573176
return LifetimeDependenceInfo::get(decl);
31583177
}
31593178

0 commit comments

Comments
 (0)