10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
- #include " swift/AST/LifetimeDependence.h"
14
13
#include " TypeChecker.h"
14
+
15
15
#include " swift/AST/ASTContext.h"
16
16
#include " swift/AST/Decl.h"
17
+ #include " swift/AST/LifetimeDependence.h"
17
18
#include " swift/AST/ParameterList.h"
18
19
#include " swift/AST/Type.h"
19
20
#include " swift/AST/TypeRepr.h"
@@ -62,6 +63,28 @@ void LifetimeDependenceInfo::Profile(llvm::FoldingSetNodeID &ID) const {
62
63
}
63
64
}
64
65
66
+ LifetimeDependenceInfo LifetimeDependenceInfo::getForParamIndex (
67
+ AbstractFunctionDecl *afd, unsigned index, ValueOwnership ownership) {
68
+ auto *dc = afd->getDeclContext ();
69
+ auto &ctx = dc->getASTContext ();
70
+ unsigned capacity = afd->getParameters ()->size () + 1 ;
71
+ auto indexSubset = IndexSubset::get (ctx, capacity, {index});
72
+ if (ownership == ValueOwnership::Owned) {
73
+ return LifetimeDependenceInfo{/* inheritLifetimeParamIndices*/ indexSubset,
74
+ /* borrowLifetimeParamIndices*/ nullptr ,
75
+ /* mutateLifetimeParamIndices*/ nullptr };
76
+ }
77
+ if (ownership == ValueOwnership::Shared) {
78
+ return LifetimeDependenceInfo{/* inheritLifetimeParamIndices*/ nullptr ,
79
+ /* borrowLifetimeParamIndices*/ indexSubset,
80
+ /* mutateLifetimeParamIndices*/ nullptr };
81
+ }
82
+ assert (ownership == ValueOwnership::InOut);
83
+ return LifetimeDependenceInfo{/* inheritLifetimeParamIndices*/ nullptr ,
84
+ /* borrowLifetimeParamIndices*/ nullptr ,
85
+ /* mutateLifetimeParamIndices*/ indexSubset};
86
+ }
87
+
65
88
llvm::Optional<LifetimeDependenceInfo>
66
89
LifetimeDependenceInfo::fromTypeRepr (AbstractFunctionDecl *afd, Type resultType,
67
90
bool allowIndex) {
@@ -81,8 +104,8 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
81
104
ValueOwnership ownership) {
82
105
auto loc = specifier.getLoc ();
83
106
auto kind = specifier.getLifetimeDependenceKind ();
84
-
85
- if (resultType ->isEscapable ()) {
107
+ Type resultTypeInContext = afd-> mapTypeIntoContext (resultType);
108
+ if (resultTypeInContext ->isEscapable ()) {
86
109
diags.diagnose (loc, diag::lifetime_dependence_invalid_return_type);
87
110
return true ;
88
111
}
@@ -187,6 +210,78 @@ LifetimeDependenceInfo::fromTypeRepr(AbstractFunctionDecl *afd, Type resultType,
187
210
IndexSubset::get (ctx, mutateLifetimeParamIndices));
188
211
}
189
212
213
+ llvm::Optional<LifetimeDependenceInfo>
214
+ LifetimeDependenceInfo::infer (AbstractFunctionDecl *afd, Type resultType) {
215
+ auto *dc = afd->getDeclContext ();
216
+ auto &ctx = dc->getASTContext ();
217
+
218
+ if (!ctx.LangOpts .hasFeature (Feature::NonescapableTypes)) {
219
+ return llvm::None;
220
+ }
221
+
222
+ auto &diags = ctx.Diags ;
223
+ auto returnTypeRepr = afd->getResultTypeRepr ();
224
+ auto returnLoc = returnTypeRepr->getLoc ();
225
+ Type returnTyInContext = afd->mapTypeIntoContext (resultType);
226
+
227
+ if (returnTyInContext->isEscapable ()) {
228
+ return llvm::None;
229
+ }
230
+ if (afd->getAttrs ().hasAttribute <UnsafeNonEscapableResultAttr>()) {
231
+ return llvm::None;
232
+ }
233
+
234
+ if (afd->hasImplicitSelfDecl ()) {
235
+ auto ownership = afd->getImplicitSelfDecl ()->getValueOwnership ();
236
+ if (ownership == ValueOwnership::Default) {
237
+ diags.diagnose (
238
+ returnLoc,
239
+ diag::
240
+ lifetime_dependence_cannot_infer_wo_ownership_modifier_on_method);
241
+ return llvm::None;
242
+ }
243
+ return LifetimeDependenceInfo::getForParamIndex (afd, /* selfIndex*/ 0 ,
244
+ ownership);
245
+ }
246
+
247
+ LifetimeDependenceInfo lifetimeDependenceInfo;
248
+ ParamDecl *candidateParam = nullptr ;
249
+ unsigned paramIndex = 0 ;
250
+ bool hasParamError = false ;
251
+ for (auto *param : *afd->getParameters ()) {
252
+ Type paramTypeInContext =
253
+ afd->mapTypeIntoContext (param->getInterfaceType ());
254
+
255
+ if (paramTypeInContext->hasError ()) {
256
+ hasParamError = true ;
257
+ continue ;
258
+ }
259
+ if (param->getValueOwnership () == ValueOwnership::Default) {
260
+ continue ;
261
+ }
262
+
263
+ if (!paramTypeInContext->isEscapable () ||
264
+ paramTypeInContext->isNoncopyable ()) {
265
+ if (candidateParam) {
266
+ diags.diagnose (
267
+ returnLoc,
268
+ diag::lifetime_dependence_cannot_infer_wo_ambiguous_candidate);
269
+ return llvm::None;
270
+ }
271
+ candidateParam = param;
272
+ lifetimeDependenceInfo = LifetimeDependenceInfo::getForParamIndex (
273
+ afd, paramIndex + 1 , param->getValueOwnership ());
274
+ }
275
+ paramIndex++;
276
+ }
277
+ if (!candidateParam && !hasParamError) {
278
+ diags.diagnose (returnLoc,
279
+ diag::lifetime_dependence_cannot_infer_no_candidates);
280
+ return llvm::None;
281
+ }
282
+ return lifetimeDependenceInfo;
283
+ }
284
+
190
285
llvm::Optional<LifetimeDependenceInfo>
191
286
LifetimeDependenceInfo::get (AbstractFunctionDecl *afd, Type resultType,
192
287
bool allowIndex) {
@@ -195,7 +290,7 @@ LifetimeDependenceInfo::get(AbstractFunctionDecl *afd, Type resultType,
195
290
return llvm::None;
196
291
}
197
292
if (!isa<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
198
- return llvm::None ;
293
+ return LifetimeDependenceInfo::infer (afd, resultType) ;
199
294
}
200
295
return LifetimeDependenceInfo::fromTypeRepr (afd, resultType, allowIndex);
201
296
}
0 commit comments