Skip to content

Commit d598d04

Browse files
committed
[NFC] Reorganize lifetime dependence utilities
1 parent 12c5ca8 commit d598d04

File tree

7 files changed

+256
-207
lines changed

7 files changed

+256
-207
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define SWIFT_EXTINFO_H
2222

2323
#include "swift/AST/AutoDiff.h"
24+
#include "swift/AST/LifetimeDependence.h"
2425

2526
#include "llvm/ADT/None.h"
2627
#include "llvm/ADT/Optional.h"
@@ -157,35 +158,6 @@ class ClangTypeInfo {
157158
void dump(llvm::raw_ostream &os, const clang::ASTContext &ctx) const;
158159
};
159160

160-
class LifetimeDependenceInfo {
161-
IndexSubset *inheritLifetimeParamIndices;
162-
IndexSubset *borrowLifetimeParamIndices;
163-
IndexSubset *mutateLifetimeParamIndices;
164-
165-
public:
166-
LifetimeDependenceInfo()
167-
: inheritLifetimeParamIndices(nullptr),
168-
borrowLifetimeParamIndices(nullptr),
169-
mutateLifetimeParamIndices(nullptr) {}
170-
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
171-
IndexSubset *borrowLifetimeParamIndices,
172-
IndexSubset *mutateLifetimeParamIndices)
173-
: inheritLifetimeParamIndices(inheritLifetimeParamIndices),
174-
borrowLifetimeParamIndices(borrowLifetimeParamIndices),
175-
mutateLifetimeParamIndices(mutateLifetimeParamIndices) {}
176-
177-
operator bool() const { return !empty(); }
178-
179-
bool empty() const {
180-
return inheritLifetimeParamIndices == nullptr &&
181-
borrowLifetimeParamIndices == nullptr &&
182-
mutateLifetimeParamIndices == nullptr;
183-
}
184-
std::string getString() const;
185-
186-
void Profile(llvm::FoldingSetNodeID &ID) const;
187-
};
188-
189161
// MARK: - UnexpectedClangTypeError
190162
/// Potential errors when trying to store a Clang type in an ExtInfo.
191163
struct UnexpectedClangTypeError {

include/swift/AST/LifetimeDependence.h

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@
1717
#ifndef SWIFT_AST_LIFETIMEDEPENDENCE_H
1818
#define SWIFT_AST_LIFETIMEDEPENDENCE_H
1919

20-
#include "swift/AST/Decl.h"
20+
#include "swift/AST/Identifier.h"
21+
#include "swift/AST/IndexSubset.h"
2122
#include "swift/Basic/Debug.h"
2223
#include "swift/Basic/OptionSet.h"
23-
#include "llvm/Support/TrailingObjects.h"
24+
#include "swift/Basic/SourceLoc.h"
25+
26+
#include "llvm/ADT/ArrayRef.h"
2427

2528
namespace swift {
2629

30+
class AbstractFunctionDecl;
31+
class LifetimeDependentReturnTypeRepr;
32+
2733
enum class LifetimeDependenceKind : uint8_t {
2834
Copy = 0,
2935
Consume,
@@ -121,6 +127,42 @@ class LifetimeDependenceSpecifier {
121127
"Invalid LifetimeDependenceSpecifier::LifetimeDependenceKind");
122128
}
123129
};
130+
131+
class LifetimeDependenceInfo {
132+
IndexSubset *inheritLifetimeParamIndices;
133+
IndexSubset *borrowLifetimeParamIndices;
134+
IndexSubset *mutateLifetimeParamIndices;
135+
136+
static llvm::Optional<LifetimeDependenceInfo>
137+
fromTypeRepr(AbstractFunctionDecl *afd, Type resultType, bool allowIndex);
138+
139+
public:
140+
LifetimeDependenceInfo()
141+
: inheritLifetimeParamIndices(nullptr),
142+
borrowLifetimeParamIndices(nullptr),
143+
mutateLifetimeParamIndices(nullptr) {}
144+
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
145+
IndexSubset *borrowLifetimeParamIndices,
146+
IndexSubset *mutateLifetimeParamIndices)
147+
: inheritLifetimeParamIndices(inheritLifetimeParamIndices),
148+
borrowLifetimeParamIndices(borrowLifetimeParamIndices),
149+
mutateLifetimeParamIndices(mutateLifetimeParamIndices) {}
150+
151+
operator bool() const { return !empty(); }
152+
153+
bool empty() const {
154+
return inheritLifetimeParamIndices == nullptr &&
155+
borrowLifetimeParamIndices == nullptr &&
156+
mutateLifetimeParamIndices == nullptr;
157+
}
158+
159+
std::string getString() const;
160+
void Profile(llvm::FoldingSetNodeID &ID) const;
161+
162+
static llvm::Optional<LifetimeDependenceInfo>
163+
get(AbstractFunctionDecl *decl, Type resultType, bool allowIndex = false);
164+
};
165+
124166
} // namespace swift
125167

126168
#endif

lib/AST/ExtInfo.cpp

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -58,49 +58,6 @@ void ClangTypeInfo::dump(llvm::raw_ostream &os,
5858
}
5959
}
6060

61-
std::string LifetimeDependenceInfo::getString() const {
62-
std::string lifetimeDependenceString;
63-
auto getOnIndices = [](IndexSubset *bitvector) {
64-
std::string result;
65-
bool isFirstSetBit = true;
66-
for (unsigned i = 0; i < bitvector->getCapacity(); i++) {
67-
if (bitvector->contains(i)) {
68-
if (!isFirstSetBit) {
69-
result += ", ";
70-
}
71-
result += std::to_string(i);
72-
isFirstSetBit = false;
73-
}
74-
}
75-
return result;
76-
};
77-
if (!inheritLifetimeParamIndices->isEmpty()) {
78-
lifetimeDependenceString =
79-
"_inherit(" + getOnIndices(inheritLifetimeParamIndices) + ")";
80-
}
81-
if (!borrowLifetimeParamIndices->isEmpty()) {
82-
lifetimeDependenceString +=
83-
"_borrow(" + getOnIndices(borrowLifetimeParamIndices) + ")";
84-
}
85-
if (!mutateLifetimeParamIndices->isEmpty()) {
86-
lifetimeDependenceString +=
87-
"_mutate(" + getOnIndices(mutateLifetimeParamIndices) + ")";
88-
}
89-
return lifetimeDependenceString;
90-
}
91-
92-
void LifetimeDependenceInfo::Profile(llvm::FoldingSetNodeID &ID) const {
93-
if (inheritLifetimeParamIndices) {
94-
inheritLifetimeParamIndices->Profile(ID);
95-
}
96-
if (borrowLifetimeParamIndices) {
97-
borrowLifetimeParamIndices->Profile(ID);
98-
}
99-
if (mutateLifetimeParamIndices) {
100-
mutateLifetimeParamIndices->Profile(ID);
101-
}
102-
}
103-
10461
// MARK: - UnexpectedClangTypeError
10562

10663
llvm::Optional<UnexpectedClangTypeError>

lib/SIL/IR/TypeLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3682,7 +3682,7 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
36823682
.withConcurrent(funcType->isSendable())
36833683
.withAsync(funcType->isAsync())
36843684
.withIsolation(funcType->getIsolation())
3685-
.withLifetimeDependenceInfo(funcType->getLifetimeDependenceInfo())
3685+
.withLifetimeDependenceInfo(funcType->getLifetimeDependenceInfo())
36863686
.build();
36873687

36883688
return CanAnyFunctionType::get(

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ add_swift_host_library(swiftSema STATIC
3535
DerivedConformances.cpp
3636
ImportResolution.cpp
3737
InstrumenterSupport.cpp
38+
LifetimeDependence.cpp
3839
LookupVisibleDecls.cpp
3940
MiscDiagnostics.cpp
4041
PCMacro.cpp

lib/Sema/LifetimeDependence.cpp

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//===--- LifetimeDependence.cpp -----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/AST/LifetimeDependence.h"
14+
#include "TypeChecker.h"
15+
#include "swift/AST/ASTContext.h"
16+
#include "swift/AST/Decl.h"
17+
#include "swift/AST/ParameterList.h"
18+
#include "swift/AST/Type.h"
19+
#include "swift/AST/TypeRepr.h"
20+
21+
namespace swift {
22+
std::string LifetimeDependenceInfo::getString() const {
23+
std::string lifetimeDependenceString;
24+
auto getOnIndices = [](IndexSubset *bitvector) {
25+
std::string result;
26+
bool isFirstSetBit = true;
27+
for (unsigned i = 0; i < bitvector->getCapacity(); i++) {
28+
if (bitvector->contains(i)) {
29+
if (!isFirstSetBit) {
30+
result += ", ";
31+
}
32+
result += std::to_string(i);
33+
isFirstSetBit = false;
34+
}
35+
}
36+
return result;
37+
};
38+
if (!inheritLifetimeParamIndices->isEmpty()) {
39+
lifetimeDependenceString =
40+
"_inherit(" + getOnIndices(inheritLifetimeParamIndices) + ")";
41+
}
42+
if (!borrowLifetimeParamIndices->isEmpty()) {
43+
lifetimeDependenceString +=
44+
"_borrow(" + getOnIndices(borrowLifetimeParamIndices) + ")";
45+
}
46+
if (!mutateLifetimeParamIndices->isEmpty()) {
47+
lifetimeDependenceString +=
48+
"_mutate(" + getOnIndices(mutateLifetimeParamIndices) + ")";
49+
}
50+
return lifetimeDependenceString;
51+
}
52+
53+
void LifetimeDependenceInfo::Profile(llvm::FoldingSetNodeID &ID) const {
54+
if (inheritLifetimeParamIndices) {
55+
inheritLifetimeParamIndices->Profile(ID);
56+
}
57+
if (borrowLifetimeParamIndices) {
58+
borrowLifetimeParamIndices->Profile(ID);
59+
}
60+
if (mutateLifetimeParamIndices) {
61+
mutateLifetimeParamIndices->Profile(ID);
62+
}
63+
}
64+
65+
llvm::Optional<LifetimeDependenceInfo>
66+
LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
67+
bool allowIndex) {
68+
auto *dc = afd->getDeclContext();
69+
auto &ctx = dc->getASTContext();
70+
auto &diags = ctx.Diags;
71+
auto capacity = afd->getParameters()->size() + 1;
72+
auto lifetimeDependentRepr =
73+
cast<LifetimeDependentReturnTypeRepr>(afd->getResultTypeRepr());
74+
75+
SmallBitVector inheritLifetimeParamIndices(capacity);
76+
SmallBitVector borrowLifetimeParamIndices(capacity);
77+
SmallBitVector mutateLifetimeParamIndices(capacity);
78+
79+
auto updateLifetimeDependenceInfo = [&](LifetimeDependenceSpecifier specifier,
80+
unsigned paramIndexToSet,
81+
ValueOwnership ownership) {
82+
auto loc = specifier.getLoc();
83+
auto kind = specifier.getLifetimeDependenceKind();
84+
85+
if (resultType->isEscapable()) {
86+
diags.diagnose(loc, diag::lifetime_dependence_invalid_return_type);
87+
return true;
88+
}
89+
90+
if (ownership == ValueOwnership::Default) {
91+
diags.diagnose(loc, diag::lifetime_dependence_missing_ownership_modifier);
92+
return true;
93+
}
94+
if (kind == LifetimeDependenceKind::Borrow &&
95+
ownership != ValueOwnership::Shared) {
96+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "borrow",
97+
getOwnershipSpelling(ownership));
98+
return true;
99+
}
100+
if (kind == LifetimeDependenceKind::Mutate &&
101+
ownership != ValueOwnership::InOut) {
102+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "mutate",
103+
getOwnershipSpelling(ownership));
104+
return true;
105+
}
106+
if (kind == LifetimeDependenceKind::Consume &&
107+
ownership != ValueOwnership::Owned) {
108+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "consume",
109+
getOwnershipSpelling(ownership));
110+
return true;
111+
}
112+
if (inheritLifetimeParamIndices.test(paramIndexToSet) ||
113+
borrowLifetimeParamIndices.test(paramIndexToSet)) {
114+
diags.diagnose(loc, diag::lifetime_dependence_duplicate_param_id);
115+
return true;
116+
}
117+
if (kind == LifetimeDependenceKind::Copy ||
118+
kind == LifetimeDependenceKind::Consume) {
119+
inheritLifetimeParamIndices.set(paramIndexToSet);
120+
} else if (kind == LifetimeDependenceKind::Borrow) {
121+
borrowLifetimeParamIndices.set(paramIndexToSet);
122+
} else {
123+
assert(kind == LifetimeDependenceKind::Mutate);
124+
mutateLifetimeParamIndices.set(paramIndexToSet);
125+
}
126+
return false;
127+
};
128+
129+
for (auto specifier : lifetimeDependentRepr->getLifetimeDependencies()) {
130+
switch (specifier.getSpecifierKind()) {
131+
case LifetimeDependenceSpecifier::SpecifierKind::Named: {
132+
bool foundParamName = false;
133+
unsigned paramIndexToSet = 1;
134+
for (auto *param : *afd->getParameters()) {
135+
if (param->getParameterName() == specifier.getName()) {
136+
foundParamName = true;
137+
if (updateLifetimeDependenceInfo(specifier, paramIndexToSet,
138+
param->getValueOwnership())) {
139+
return llvm::None;
140+
}
141+
break;
142+
}
143+
paramIndexToSet++;
144+
}
145+
if (!foundParamName) {
146+
diags.diagnose(specifier.getLoc(),
147+
diag::lifetime_dependence_invalid_param_name,
148+
specifier.getName());
149+
return llvm::None;
150+
}
151+
break;
152+
}
153+
case LifetimeDependenceSpecifier::SpecifierKind::Ordered: {
154+
auto paramIndex = specifier.getIndex();
155+
if (paramIndex > afd->getParameters()->size()) {
156+
diags.diagnose(specifier.getLoc(),
157+
diag::lifetime_dependence_invalid_param_index,
158+
paramIndex);
159+
return llvm::None;
160+
}
161+
if (updateLifetimeDependenceInfo(
162+
specifier, /*paramIndexToSet*/ specifier.getIndex() + 1,
163+
afd->getParameters()->get(paramIndex)->getValueOwnership())) {
164+
return llvm::None;
165+
}
166+
break;
167+
}
168+
case LifetimeDependenceSpecifier::SpecifierKind::Self: {
169+
if (!afd->hasImplicitSelfDecl()) {
170+
diags.diagnose(specifier.getLoc(),
171+
diag::lifetime_dependence_invalid_self);
172+
return llvm::None;
173+
}
174+
if (updateLifetimeDependenceInfo(
175+
specifier, /*selfIndex*/ 0,
176+
afd->getImplicitSelfDecl()->getValueOwnership())) {
177+
return llvm::None;
178+
}
179+
break;
180+
}
181+
}
182+
}
183+
184+
return LifetimeDependenceInfo(
185+
IndexSubset::get(ctx, inheritLifetimeParamIndices),
186+
IndexSubset::get(ctx, borrowLifetimeParamIndices),
187+
IndexSubset::get(ctx, mutateLifetimeParamIndices));
188+
}
189+
190+
llvm::Optional<LifetimeDependenceInfo>
191+
LifetimeDependenceInfo::get(AbstractFunctionDecl *afd, Type resultType,
192+
bool allowIndex) {
193+
auto *returnTypeRepr = afd->getResultTypeRepr();
194+
if (!returnTypeRepr) {
195+
return llvm::None;
196+
}
197+
if (!isa<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
198+
return llvm::None;
199+
}
200+
return LifetimeDependenceInfo::fromTypeRepr(afd, resultType, allowIndex);
201+
}
202+
} // namespace swift

0 commit comments

Comments
 (0)