Skip to content

Commit db24b6f

Browse files
committed
Support lifetime dependence inference on enum elements
1 parent ccda38b commit db24b6f

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
@@ -8779,7 +8779,8 @@ class EnumCaseDecl final : public Decl,
87798779
/// EnumCaseDecl.
87808780
class EnumElementDecl : public DeclContext, public ValueDecl {
87818781
friend class EnumRawValuesRequest;
8782-
8782+
friend class LifetimeDependenceInfoRequest;
8783+
87838784
/// This is the type specified with the enum element, for
87848785
/// example 'Int' in 'case Y(Int)'. This is null if there is no type
87858786
/// associated with this element, as in 'case Z' or in all elements of enum
@@ -8791,6 +8792,11 @@ class EnumElementDecl : public DeclContext, public ValueDecl {
87918792
/// The raw value literal for the enum element, or null.
87928793
LiteralExpr *RawValueExpr;
87938794

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

include/swift/AST/LifetimeDependence.h

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

330329
/// Builds LifetimeDependenceInfo from SIL
331330
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
@@ -5114,8 +5114,7 @@ class ImportDeclRequest
51145114
class LifetimeDependenceInfoRequest
51155115
: public SimpleRequest<
51165116
LifetimeDependenceInfoRequest,
5117-
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>(
5118-
AbstractFunctionDecl *),
5117+
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>(ValueDecl *),
51195118
RequestFlags::SeparatelyCached | RequestFlags::SplitCached> {
51205119
public:
51215120
using SimpleRequest::SimpleRequest;
@@ -5124,7 +5123,7 @@ class LifetimeDependenceInfoRequest
51245123
friend SimpleRequest;
51255124

51265125
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
5127-
evaluate(Evaluator &evaluator, AbstractFunctionDecl *AFD) const;
5126+
evaluate(Evaluator &evaluator, ValueDecl *AFD) const;
51285127

51295128
public:
51305129
// 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(
@@ -1417,8 +1462,12 @@ class LifetimeDependenceChecker {
14171462
};
14181463

14191464
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
1420-
LifetimeDependenceInfo::get(AbstractFunctionDecl *afd) {
1421-
return LifetimeDependenceChecker(afd).checkFuncDecl();
1465+
LifetimeDependenceInfo::get(ValueDecl *decl) {
1466+
if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
1467+
return LifetimeDependenceChecker(afd).checkFuncDecl();
1468+
}
1469+
auto *eed = cast<EnumElementDecl>(decl);
1470+
return LifetimeDependenceChecker(eed).checkEnumElementDecl();
14221471
}
14231472

14241473
// 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
@@ -2734,24 +2734,36 @@ void ExpandBodyMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
27342734

27352735
std::optional<std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>>
27362736
LifetimeDependenceInfoRequest::getCachedResult() const {
2737-
auto *func = std::get<0>(getStorage());
2737+
auto *decl = std::get<0>(getStorage());
2738+
bool noLifetimeDependenceInfo;
27382739

2739-
if (func->LazySemanticInfo.NoLifetimeDependenceInfo)
2740+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
2741+
noLifetimeDependenceInfo = func->LazySemanticInfo.NoLifetimeDependenceInfo;
2742+
} else {
2743+
auto *eed = cast<EnumElementDecl>(decl);
2744+
noLifetimeDependenceInfo = eed->LazySemanticInfo.NoLifetimeDependenceInfo;
2745+
}
2746+
2747+
if (noLifetimeDependenceInfo)
27402748
return std::optional(std::optional<LifetimeDependenceInfo>());
27412749

2742-
return func->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
2750+
return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
27432751
}
27442752

27452753
void LifetimeDependenceInfoRequest::cacheResult(
27462754
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>> result) const {
2747-
auto *func = std::get<0>(getStorage());
2748-
2755+
auto *decl = std::get<0>(getStorage());
2756+
27492757
if (!result) {
2750-
func->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
2751-
return;
2758+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
2759+
func->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
2760+
return;
2761+
}
2762+
auto *eed = cast<EnumElementDecl>(decl);
2763+
eed->LazySemanticInfo.NoLifetimeDependenceInfo = 1;
27522764
}
27532765

2754-
func->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
2766+
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
27552767
}
27562768

27572769
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckDecl.cpp

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

2410+
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
2411+
getLifetimeDependencies(ASTContext &context, EnumElementDecl *enumElemDecl) {
2412+
return evaluateOrDefault(context.evaluator,
2413+
LifetimeDependenceInfoRequest{enumElemDecl},
2414+
std::nullopt);
2415+
}
2416+
24102417
Type
24112418
InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
24122419
auto &Context = D->getASTContext();
@@ -2696,13 +2703,25 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
26962703
resultTy = FunctionType::get(argTy, resultTy, info);
26972704
}
26982705

2706+
auto lifetimeDependenceInfo = getLifetimeDependencies(Context, EED);
2707+
26992708
// FIXME: Verify ExtInfo state is correct, not working by accident.
27002709
if (auto genericSig = ED->getGenericSignature()) {
2701-
GenericFunctionType::ExtInfo info;
2702-
resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy, info);
2710+
GenericFunctionType::ExtInfoBuilder infoBuilder;
2711+
if (lifetimeDependenceInfo.has_value()) {
2712+
infoBuilder =
2713+
infoBuilder.withLifetimeDependencies(*lifetimeDependenceInfo);
2714+
}
2715+
resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy,
2716+
infoBuilder.build());
2717+
27032718
} else {
2704-
FunctionType::ExtInfo info;
2705-
resultTy = FunctionType::get({selfTy}, resultTy, info);
2719+
FunctionType::ExtInfoBuilder infoBuilder;
2720+
if (lifetimeDependenceInfo.has_value()) {
2721+
infoBuilder =
2722+
infoBuilder.withLifetimeDependencies(*lifetimeDependenceInfo);
2723+
}
2724+
resultTy = FunctionType::get({selfTy}, resultTy, infoBuilder.build());
27062725
}
27072726

27082727
return resultTy;
@@ -3151,7 +3170,7 @@ ImplicitKnownProtocolConformanceRequest::evaluate(Evaluator &evaluator,
31513170

31523171
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
31533172
LifetimeDependenceInfoRequest::evaluate(Evaluator &evaluator,
3154-
AbstractFunctionDecl *decl) const {
3173+
ValueDecl *decl) const {
31553174
return LifetimeDependenceInfo::get(decl);
31563175
}
31573176

0 commit comments

Comments
 (0)