Skip to content

Commit f5e5789

Browse files
authored
Merge pull request #71206 from meg-gupta/lifetimedepsil
Lower lifetime dependence info into SIL and infer when absent
2 parents f2d68a2 + 4dcda84 commit f5e5789

21 files changed

+644
-243
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7807,10 +7807,22 @@ ERROR(pack_iteration_where_clause_not_supported, none,
78077807
"functions, methods, initializers",
78087808
())
78097809
ERROR(lifetime_dependence_invalid_return_type, none,
7810-
"lifetime dependence specifiers can only be specifier on ~Escapable "
7811-
"results", ())
7810+
"lifetime dependence can only be specified on ~Escapable results", ())
78127811
ERROR(lifetime_dependence_missing_ownership_modifier, none,
78137812
"lifetime dependence can only be specified on parameters with ownership "
78147813
"modifiers (borrowing, consuming, inout)", ())
7814+
ERROR(lifetime_dependence_cannot_infer_wo_ownership_modifier_on_method, none,
7815+
"cannot infer lifetime dependence, specify ownership modifier for the "
7816+
"method",
7817+
())
7818+
ERROR(lifetime_dependence_cannot_infer_wo_ambiguous_candidate, none,
7819+
"cannot infer lifetime dependence, multiple ~Escapable or ~Copyable "
7820+
"parameters with ownership modifiers, specify explicit lifetime "
7821+
"dependence",
7822+
())
7823+
ERROR(lifetime_dependence_cannot_infer_no_candidates, none,
7824+
"cannot infer lifetime dependence, no ~Escapable or ~Copyable "
7825+
"parameters with ownership modifiers present",
7826+
())
78157827
#define UNDEFINE_DIAGNOSTIC_MACROS
78167828
#include "DefineDiagnosticMacros.h"

include/swift/AST/ExtInfo.h

Lines changed: 60 additions & 62 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,27 +158,6 @@ class ClangTypeInfo {
157158
void dump(llvm::raw_ostream &os, const clang::ASTContext &ctx) const;
158159
};
159160

160-
class LifetimeDependenceInfo {
161-
IndexSubset *copyLifetimeParamIndices;
162-
IndexSubset *borrowLifetimeParamIndices;
163-
164-
public:
165-
LifetimeDependenceInfo()
166-
: copyLifetimeParamIndices(nullptr), borrowLifetimeParamIndices(nullptr) {
167-
}
168-
LifetimeDependenceInfo(IndexSubset *copyLifetimeParamIndices,
169-
IndexSubset *borrowLifetimeParamIndices)
170-
: copyLifetimeParamIndices(copyLifetimeParamIndices),
171-
borrowLifetimeParamIndices(borrowLifetimeParamIndices) {}
172-
173-
operator bool() const { return empty(); }
174-
175-
bool empty() const {
176-
return copyLifetimeParamIndices == nullptr &&
177-
borrowLifetimeParamIndices == nullptr;
178-
}
179-
};
180-
181161
// MARK: - UnexpectedClangTypeError
182162
/// Potential errors when trying to store a Clang type in an ExtInfo.
183163
struct UnexpectedClangTypeError {
@@ -684,20 +664,21 @@ class ASTExtInfoBuilder {
684664
lifetimeDependenceInfo);
685665
}
686666

667+
void Profile(llvm::FoldingSetNodeID &ID) const {
668+
ID.AddInteger(bits);
669+
ID.AddPointer(clangTypeInfo.getType());
670+
ID.AddPointer(globalActor.getPointer());
671+
ID.AddPointer(thrownError.getPointer());
672+
lifetimeDependenceInfo.Profile(ID);
673+
}
674+
687675
bool isEqualTo(ASTExtInfoBuilder other, bool useClangTypes) const {
688676
return bits == other.bits &&
689677
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true) &&
690678
globalActor.getPointer() == other.globalActor.getPointer() &&
691679
thrownError.getPointer() == other.thrownError.getPointer() &&
692680
lifetimeDependenceInfo == other.lifetimeDependenceInfo;
693681
}
694-
695-
constexpr std::tuple<unsigned, const void *, const void *, const void *>
696-
getFuncAttrKey() const {
697-
return std::make_tuple(
698-
bits, clangTypeInfo.getType(), globalActor.getPointer(),
699-
thrownError.getPointer());
700-
}
701682
}; // end ASTExtInfoBuilder
702683

703684
// MARK: - ASTExtInfo
@@ -844,14 +825,11 @@ class ASTExtInfo {
844825
return builder.withLifetimeDependenceInfo(lifetimeDependenceInfo).build();
845826
}
846827

828+
void Profile(llvm::FoldingSetNodeID &ID) const { builder.Profile(ID); }
829+
847830
bool isEqualTo(ASTExtInfo other, bool useClangTypes) const {
848831
return builder.isEqualTo(other.builder, useClangTypes);
849832
}
850-
851-
constexpr std::tuple<unsigned, const void *, const void *, const void *>
852-
getFuncAttrKey() const {
853-
return builder.getFuncAttrKey();
854-
}
855833
}; // end ASTExtInfo
856834

857835
// MARK: - SILFunctionLanguage
@@ -922,11 +900,15 @@ class SILExtInfoBuilder {
922900

923901
ClangTypeInfo clangTypeInfo;
924902

903+
LifetimeDependenceInfo lifetimeDependenceInfo;
904+
925905
using Language = SILFunctionLanguage;
926906
using Representation = SILFunctionTypeRepresentation;
927907

928-
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
929-
: bits(bits), clangTypeInfo(clangTypeInfo.getCanonical()) {}
908+
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo,
909+
LifetimeDependenceInfo lifetimeDependenceInfo)
910+
: bits(bits), clangTypeInfo(clangTypeInfo.getCanonical()),
911+
lifetimeDependenceInfo(lifetimeDependenceInfo) {}
930912

931913
static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric,
932914
bool isNoEscape, bool isSendable,
@@ -948,23 +930,24 @@ class SILExtInfoBuilder {
948930
: SILExtInfoBuilder(makeBits(SILFunctionTypeRepresentation::Thick, false,
949931
false, false, false, false,
950932
DifferentiabilityKind::NonDifferentiable),
951-
ClangTypeInfo(nullptr)) {}
933+
ClangTypeInfo(nullptr), LifetimeDependenceInfo()) {}
952934

953935
SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape,
954936
bool isSendable, bool isAsync, bool isUnimplementable,
955-
DifferentiabilityKind diffKind, const clang::Type *type)
956-
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape,
957-
isSendable, isAsync, isUnimplementable,
958-
diffKind),
959-
ClangTypeInfo(type)) {}
937+
DifferentiabilityKind diffKind, const clang::Type *type,
938+
LifetimeDependenceInfo lifetimeDependenceInfo)
939+
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape, isSendable,
940+
isAsync, isUnimplementable, diffKind),
941+
ClangTypeInfo(type), lifetimeDependenceInfo) {}
960942

961943
// Constructor for polymorphic type.
962944
SILExtInfoBuilder(ASTExtInfoBuilder info, bool isPseudogeneric)
963945
: SILExtInfoBuilder(makeBits(info.getSILRepresentation(), isPseudogeneric,
964946
info.isNoEscape(), info.isSendable(),
965947
info.isAsync(), /*unimplementable*/ false,
966948
info.getDifferentiabilityKind()),
967-
info.getClangTypeInfo()) {}
949+
info.getClangTypeInfo(),
950+
info.getLifetimeDependenceInfo()) {}
968951

969952
void checkInvariants() const;
970953

@@ -1008,6 +991,10 @@ class SILExtInfoBuilder {
1008991
/// Get the underlying ClangTypeInfo value.
1009992
ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; }
1010993

994+
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
995+
return lifetimeDependenceInfo;
996+
}
997+
1011998
constexpr bool hasSelfParam() const {
1012999
switch (getRepresentation()) {
10131000
case Representation::Thick:
@@ -1057,59 +1044,66 @@ class SILExtInfoBuilder {
10571044
SILExtInfoBuilder withRepresentation(Representation rep) const {
10581045
return SILExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
10591046
shouldStoreClangType(rep) ? clangTypeInfo
1060-
: ClangTypeInfo());
1047+
: ClangTypeInfo(),
1048+
lifetimeDependenceInfo);
10611049
}
10621050
[[nodiscard]]
10631051
SILExtInfoBuilder withIsPseudogeneric(bool isPseudogeneric = true) const {
10641052
return SILExtInfoBuilder(isPseudogeneric ? (bits | PseudogenericMask)
10651053
: (bits & ~PseudogenericMask),
1066-
clangTypeInfo);
1054+
clangTypeInfo, lifetimeDependenceInfo);
10671055
}
10681056
[[nodiscard]]
10691057
SILExtInfoBuilder withNoEscape(bool noEscape = true) const {
10701058
return SILExtInfoBuilder(noEscape ? (bits | NoEscapeMask)
10711059
: (bits & ~NoEscapeMask),
1072-
clangTypeInfo);
1060+
clangTypeInfo, lifetimeDependenceInfo);
10731061
}
10741062
[[nodiscard]]
10751063
SILExtInfoBuilder withConcurrent(bool isSendable = true) const {
10761064
return SILExtInfoBuilder(isSendable ? (bits | SendableMask)
1077-
: (bits & ~SendableMask),
1078-
clangTypeInfo);
1065+
: (bits & ~SendableMask),
1066+
clangTypeInfo, lifetimeDependenceInfo);
10791067
}
10801068
[[nodiscard]]
10811069
SILExtInfoBuilder withAsync(bool isAsync = true) const {
10821070
return SILExtInfoBuilder(isAsync ? (bits | AsyncMask) : (bits & ~AsyncMask),
1083-
clangTypeInfo);
1071+
clangTypeInfo, lifetimeDependenceInfo);
10841072
}
10851073
[[nodiscard]]
10861074
SILExtInfoBuilder withUnimplementable(bool isUnimplementable = true) const {
10871075
return SILExtInfoBuilder(isUnimplementable ? (bits | UnimplementableMask)
10881076
: (bits & ~UnimplementableMask),
1089-
clangTypeInfo);
1077+
clangTypeInfo, lifetimeDependenceInfo);
10901078
}
10911079
[[nodiscard]]
10921080
SILExtInfoBuilder
10931081
withDifferentiabilityKind(DifferentiabilityKind differentiability) const {
10941082
return SILExtInfoBuilder(
10951083
(bits & ~DifferentiabilityMask) |
10961084
((unsigned)differentiability << DifferentiabilityMaskOffset),
1097-
clangTypeInfo);
1085+
clangTypeInfo, lifetimeDependenceInfo);
10981086
}
10991087
[[nodiscard]]
11001088
SILExtInfoBuilder withClangFunctionType(const clang::Type *type) const {
1101-
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical());
1089+
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical(),
1090+
lifetimeDependenceInfo);
1091+
}
1092+
[[nodiscard]] SILExtInfoBuilder withLifetimeDependenceInfo(
1093+
LifetimeDependenceInfo lifetimeDependenceInfo) const {
1094+
return SILExtInfoBuilder(bits, clangTypeInfo, lifetimeDependenceInfo);
11021095
}
11031096

1097+
void Profile(llvm::FoldingSetNodeID &ID) const {
1098+
ID.AddInteger(bits);
1099+
ID.AddPointer(clangTypeInfo.getType());
1100+
lifetimeDependenceInfo.Profile(ID);
1101+
}
11041102

11051103
bool isEqualTo(SILExtInfoBuilder other, bool useClangTypes) const {
11061104
return bits == other.bits &&
11071105
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true);
11081106
}
1109-
1110-
constexpr std::pair<unsigned, const void *> getFuncAttrKey() const {
1111-
return std::make_pair(bits, clangTypeInfo.getType());
1112-
}
11131107
}; // end SILExtInfoBuilder
11141108

11151109
// MARK: - SILExtInfo
@@ -1129,8 +1123,9 @@ class SILExtInfo {
11291123
// Only for use by SILExtInfoBuilder::build. Don't use it elsewhere!
11301124
SILExtInfo(SILExtInfoBuilder builder) : builder(builder) {}
11311125

1132-
SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo)
1133-
: builder(bits, clangTypeInfo) {
1126+
SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo,
1127+
LifetimeDependenceInfo lifetimeDependenceInfo)
1128+
: builder(bits, clangTypeInfo, lifetimeDependenceInfo) {
11341129
builder.checkInvariants();
11351130
};
11361131

@@ -1148,7 +1143,8 @@ class SILExtInfo {
11481143
static SILExtInfo getThin() {
11491144
return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false,
11501145
false, false, false, false,
1151-
DifferentiabilityKind::NonDifferentiable, nullptr)
1146+
DifferentiabilityKind::NonDifferentiable, nullptr,
1147+
LifetimeDependenceInfo())
11521148
.build();
11531149
}
11541150

@@ -1187,6 +1183,10 @@ class SILExtInfo {
11871183

11881184
ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); }
11891185

1186+
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
1187+
return builder.getLifetimeDependenceInfo();
1188+
}
1189+
11901190
constexpr bool hasSelfParam() const { return builder.hasSelfParam(); }
11911191

11921192
constexpr bool hasContext() const { return builder.hasContext(); }
@@ -1217,14 +1217,12 @@ class SILExtInfo {
12171217
return builder.withUnimplementable(isUnimplementable).build();
12181218
}
12191219

1220+
void Profile(llvm::FoldingSetNodeID &ID) const { builder.Profile(ID); }
1221+
12201222
bool isEqualTo(SILExtInfo other, bool useClangTypes) const {
12211223
return builder.isEqualTo(other.builder, useClangTypes);
12221224
}
12231225

1224-
constexpr std::pair<unsigned, const void *> getFuncAttrKey() const {
1225-
return builder.getFuncAttrKey();
1226-
}
1227-
12281226
llvm::Optional<UnexpectedClangTypeError> checkClangType() const;
12291227
};
12301228

include/swift/AST/LifetimeDependence.h

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,20 @@
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"
22+
#include "swift/AST/Ownership.h"
2123
#include "swift/Basic/Debug.h"
2224
#include "swift/Basic/OptionSet.h"
23-
#include "llvm/Support/TrailingObjects.h"
25+
#include "swift/Basic/SourceLoc.h"
26+
27+
#include "llvm/ADT/ArrayRef.h"
2428

2529
namespace swift {
2630

31+
class AbstractFunctionDecl;
32+
class LifetimeDependentReturnTypeRepr;
33+
2734
enum class LifetimeDependenceKind : uint8_t {
2835
Copy = 0,
2936
Consume,
@@ -93,6 +100,7 @@ class LifetimeDependenceSpecifier {
93100
assert(specifierKind == SpecifierKind::Ordered);
94101
return value.Ordered.index;
95102
}
103+
96104
std::string getParamString() const {
97105
switch (specifierKind) {
98106
case SpecifierKind::Named:
@@ -104,7 +112,65 @@ class LifetimeDependenceSpecifier {
104112
}
105113
llvm_unreachable("Invalid LifetimeDependenceSpecifier::SpecifierKind");
106114
}
115+
116+
StringRef getLifetimeDependenceKindString() const {
117+
switch (lifetimeDependenceKind) {
118+
case LifetimeDependenceKind::Borrow:
119+
return "_borrow";
120+
case LifetimeDependenceKind::Consume:
121+
return "_consume";
122+
case LifetimeDependenceKind::Copy:
123+
return "_copy";
124+
case LifetimeDependenceKind::Mutate:
125+
return "_mutate";
126+
}
127+
llvm_unreachable(
128+
"Invalid LifetimeDependenceSpecifier::LifetimeDependenceKind");
129+
}
107130
};
131+
132+
class LifetimeDependenceInfo {
133+
IndexSubset *inheritLifetimeParamIndices;
134+
IndexSubset *borrowLifetimeParamIndices;
135+
IndexSubset *mutateLifetimeParamIndices;
136+
137+
static LifetimeDependenceInfo getForParamIndex(AbstractFunctionDecl *afd,
138+
unsigned index,
139+
ValueOwnership ownership);
140+
141+
static llvm::Optional<LifetimeDependenceInfo>
142+
fromTypeRepr(AbstractFunctionDecl *afd, Type resultType, bool allowIndex);
143+
144+
static llvm::Optional<LifetimeDependenceInfo> infer(AbstractFunctionDecl *afd,
145+
Type resultType);
146+
147+
public:
148+
LifetimeDependenceInfo()
149+
: inheritLifetimeParamIndices(nullptr),
150+
borrowLifetimeParamIndices(nullptr),
151+
mutateLifetimeParamIndices(nullptr) {}
152+
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
153+
IndexSubset *borrowLifetimeParamIndices,
154+
IndexSubset *mutateLifetimeParamIndices)
155+
: inheritLifetimeParamIndices(inheritLifetimeParamIndices),
156+
borrowLifetimeParamIndices(borrowLifetimeParamIndices),
157+
mutateLifetimeParamIndices(mutateLifetimeParamIndices) {}
158+
159+
operator bool() const { return !empty(); }
160+
161+
bool empty() const {
162+
return inheritLifetimeParamIndices == nullptr &&
163+
borrowLifetimeParamIndices == nullptr &&
164+
mutateLifetimeParamIndices == nullptr;
165+
}
166+
167+
std::string getString() const;
168+
void Profile(llvm::FoldingSetNodeID &ID) const;
169+
170+
static llvm::Optional<LifetimeDependenceInfo>
171+
get(AbstractFunctionDecl *decl, Type resultType, bool allowIndex = false);
172+
};
173+
108174
} // namespace swift
109175

110176
#endif

0 commit comments

Comments
 (0)