@@ -240,6 +240,112 @@ getLifetimeDependenceKind(LifetimeEntry specifier, AbstractFunctionDecl *afd,
240
240
return lifetimeKind;
241
241
}
242
242
243
+ static bool populateLifetimeDependence (AbstractFunctionDecl *afd,
244
+ LifetimeEntry entry,
245
+ SmallBitVector &inheritIndices,
246
+ SmallBitVector &scopeIndices,
247
+ bool &isImmortal) {
248
+ auto updateLifetimeIndices =
249
+ [&](LifetimeEntry entry, unsigned paramIndexToSet,
250
+ std::optional<LifetimeDependenceKind> lifetimeKind) {
251
+ auto loc = entry.getLoc ();
252
+ if (!lifetimeKind.has_value ()) {
253
+ return true ;
254
+ }
255
+ if (inheritIndices.test (paramIndexToSet) ||
256
+ scopeIndices.test (paramIndexToSet)) {
257
+ diags.diagnose (loc, diag::lifetime_dependence_duplicate_param_id);
258
+ return true ;
259
+ }
260
+ if (lifetimeKind == LifetimeDependenceKind::Inherit) {
261
+ inheritIndices.set (paramIndexToSet);
262
+ } else {
263
+ assert (lifetimeKind == LifetimeDependenceKind::Scope);
264
+ scopeIndices.set (paramIndexToSet);
265
+ }
266
+ return false ;
267
+ };
268
+
269
+ switch (entry.getLifetimeEntryKind ()) {
270
+ case LifetimeEntryKind::Immortal: {
271
+ auto immortalParam =
272
+ std::find_if (afd->getParameters ()->begin (), afd->getParameters ()->end (),
273
+ [](ParamDecl *param) {
274
+ return strcmp (param->getName ().get (), " immortal" ) == 0 ;
275
+ });
276
+ if (immortalParam != afd->getParameters ()->end ()) {
277
+ diags.diagnose (*immortalParam,
278
+ diag::lifetime_dependence_immortal_conflict_name);
279
+ return true ;
280
+ }
281
+ if (inheritIndicies.any () || scopeIndices.any ()) {
282
+ diags.diagnose (entry.getLoc (), diag::lifetime_dependence_immortal_alone);
283
+ return true ;
284
+ }
285
+ isImmortal = true ;
286
+ return false ;
287
+ }
288
+ case LifetimeEntryKind::Named: {
289
+ unsigned paramIndex = 0 ;
290
+ ParamDecl *candidateParam = nullptr ;
291
+ for (auto *param : *afd->getParameters ()) {
292
+ if (param->getParameterName () == entry.getName ()) {
293
+ candidateParam = param;
294
+ break ;
295
+ }
296
+ paramIndex++;
297
+ }
298
+ if (!candidateParam) {
299
+ diags.diagnose (entry.getLoc (),
300
+ diag::lifetime_dependence_invalid_param_name,
301
+ entry.getName ());
302
+ return true ;
303
+ }
304
+ if (isImmortal) {
305
+ diags.diagnose (entry.getLoc (), diag::lifetime_dependence_immortal_alone);
306
+ return true ;
307
+ }
308
+ auto lifetimeKind = getLifetimeDependenceKind (entry, afd, candidateParam);
309
+ return updateLifetimeIndices (entry, paramIndex, lifetimeKind);
310
+ }
311
+ case LifetimeEntryKind::Ordered: {
312
+ auto index = entry.getIndex ();
313
+ if (index >= afd->getParameters ()->size ()) {
314
+ diags.diagnose (entry.getLoc (),
315
+ diag::lifetime_dependence_invalid_param_index, index);
316
+ return true ;
317
+ }
318
+ if (isImmortal) {
319
+ diags.diagnose (entry.getLoc (), diag::lifetime_dependence_immortal_alone);
320
+ return true ;
321
+ }
322
+ auto candidateParam = afd->getParameters ()->get (index);
323
+ auto lifetimeKind = getLifetimeDependenceKind (entry, afd, candidateParam);
324
+ return updateLifetimeIndices (entry, index, lifetimeKind);
325
+ }
326
+ case LifetimeEntryKind::Self: {
327
+ if (!afd->hasImplicitSelfDecl ()) {
328
+ diags.diagnose (entry.getLoc (),
329
+ diag::lifetime_dependence_invalid_self_in_static);
330
+ return true ;
331
+ }
332
+ if (isa<ConstructorDecl>(afd)) {
333
+ diags.diagnose (entry.getLoc (),
334
+ diag::lifetime_dependence_invalid_self_in_init);
335
+ return true ;
336
+ }
337
+ if (isImmortal) {
338
+ diags.diagnose (entry.getLoc (), diag::lifetime_dependence_immortal_alone);
339
+ return true ;
340
+ }
341
+ auto *selfDecl = afd->getImplicitSelfDecl ();
342
+ auto lifetimeKind = getLifetimeDependenceKind (entry, afd, selfDecl);
343
+ return updateLifetimeIndices (
344
+ entry, /* selfIndex */ afd->getParameters ()->size (), lifetimeKind);
345
+ }
346
+ }
347
+ }
348
+
243
349
std::optional<LifetimeDependenceInfo>
244
350
LifetimeDependenceInfo::fromDependsOn (AbstractFunctionDecl *afd,
245
351
TypeRepr *targetTypeRepr, Type targetType,
@@ -264,122 +370,28 @@ LifetimeDependenceInfo::fromDependsOn(AbstractFunctionDecl *afd,
264
370
? (afd->getParameters ()->size () + 1 )
265
371
: afd->getParameters ()->size ();
266
372
267
- SmallBitVector inheritLifetimeParamIndices (capacity);
268
- SmallBitVector scopeLifetimeParamIndices (capacity);
373
+ SmallBitVector inheritIndices (capacity);
374
+ SmallBitVector scopeIndices (capacity);
375
+ bool isImmortal = false ;
376
+ bool hasError = false ;
269
377
270
- auto updateLifetimeDependenceInfo =
271
- [&](LifetimeEntry specifier, unsigned paramIndexToSet,
272
- std::optional<LifetimeDependenceKind> lifetimeKind) {
273
- auto loc = specifier.getLoc ();
274
- if (!lifetimeKind.has_value ()) {
275
- return true ;
276
- }
277
- if (inheritLifetimeParamIndices.test (paramIndexToSet) ||
278
- scopeLifetimeParamIndices.test (paramIndexToSet)) {
279
- diags.diagnose (loc, diag::lifetime_dependence_duplicate_param_id);
280
- return true ;
281
- }
282
- if (lifetimeKind == LifetimeDependenceKind::Inherit) {
283
- inheritLifetimeParamIndices.set (paramIndexToSet);
284
- } else {
285
- assert (lifetimeKind == LifetimeDependenceKind::Scope);
286
- scopeLifetimeParamIndices.set (paramIndexToSet);
287
- }
288
- return false ;
289
- };
290
-
291
- for (auto specifier : lifetimeDependentRepr->getLifetimeDependencies ()) {
292
- switch (specifier.getLifetimeEntryKind ()) {
293
- case LifetimeEntryKind::Immortal: {
294
- auto immortalParam =
295
- std::find_if (afd->getParameters ()->begin (),
296
- afd->getParameters ()->end (), [](ParamDecl *param) {
297
- return strcmp (param->getName ().get (), " immortal" ) == 0 ;
298
- });
299
- if (immortalParam != afd->getParameters ()->end ()) {
300
- diags.diagnose (*immortalParam,
301
- diag::lifetime_dependence_immortal_conflict_name);
302
- }
303
-
304
- return LifetimeDependenceInfo (nullptr , nullptr , targetIndex,
305
- /* isImmortal*/ true );
306
- }
307
- case LifetimeEntryKind::Named: {
308
- unsigned paramIndex = 0 ;
309
- ParamDecl *candidateParam = nullptr ;
310
- for (auto *param : *afd->getParameters ()) {
311
- if (param->getParameterName () == specifier.getName ()) {
312
- candidateParam = param;
313
- break ;
314
- }
315
- paramIndex++;
316
- }
317
- if (!candidateParam) {
318
- diags.diagnose (specifier.getLoc (),
319
- diag::lifetime_dependence_invalid_param_name,
320
- specifier.getName ());
321
- return std::nullopt;
322
- }
323
- auto lifetimeKind =
324
- getLifetimeDependenceKind (specifier, afd, candidateParam);
325
- if (updateLifetimeDependenceInfo (specifier, paramIndex, lifetimeKind)) {
326
- return std::nullopt;
327
- }
328
-
329
- break ;
330
- }
331
- case LifetimeEntryKind::Ordered: {
332
- auto index = specifier.getIndex ();
333
- if (index >= afd->getParameters ()->size ()) {
334
- diags.diagnose (specifier.getLoc (),
335
- diag::lifetime_dependence_invalid_param_index, index);
336
- return std::nullopt;
337
- }
338
- auto candidateParam = afd->getParameters ()->get (index);
339
- auto lifetimeKind =
340
- getLifetimeDependenceKind (specifier, afd, candidateParam);
341
- if (updateLifetimeDependenceInfo (specifier, index, lifetimeKind)) {
342
- return std::nullopt;
343
- }
344
- break ;
345
- }
346
- case LifetimeEntryKind::Self: {
347
- if (!afd->hasImplicitSelfDecl ()) {
348
- diags.diagnose (specifier.getLoc (),
349
- diag::lifetime_dependence_invalid_self_in_static);
350
- return std::nullopt;
351
- }
352
- if (isa<ConstructorDecl>(afd)) {
353
- diags.diagnose (specifier.getLoc (),
354
- diag::lifetime_dependence_invalid_self_in_init);
355
- return std::nullopt;
356
- }
357
- auto *selfDecl = afd->getImplicitSelfDecl ();
358
- auto lifetimeKind = getLifetimeDependenceKind (specifier, afd, selfDecl);
359
- if (updateLifetimeDependenceInfo (
360
- specifier, /* selfIndex */ afd->getParameters ()->size (),
361
- lifetimeKind)) {
362
- return std::nullopt;
363
- }
364
- break ;
365
- }
366
- }
378
+ for (auto entry : lifetimeDependentRepr->getLifetimeDependencies ()) {
379
+ hasError |= populateLifetimeDependence (afd, entry, inheritIndices,
380
+ scopeIndices, isImmortal);
367
381
}
368
382
383
+ if (hasError) {
384
+ return std::nullopt;
385
+ }
369
386
return LifetimeDependenceInfo (
370
- inheritLifetimeParamIndices.any ()
371
- ? IndexSubset::get (ctx, inheritLifetimeParamIndices)
372
- : nullptr ,
373
- scopeLifetimeParamIndices.any ()
374
- ? IndexSubset::get (ctx, scopeLifetimeParamIndices)
375
- : nullptr ,
376
- targetIndex,
377
- /* isImmortal*/ false );
387
+ inheritIndices.any () ? IndexSubset::get (ctx, inheritIndices) : nullptr ,
388
+ scopeIndices.any () ? IndexSubset::get (ctx, scopeIndices) : nullptr ,
389
+ targetIndex, isImmortal);
378
390
}
379
391
380
392
// This utility is similar to its overloaded version that builds the
381
- // LifetimeDependenceInfo from the swift decl. Reason for duplicated code is the
382
- // apis on type and ownership is different in SIL compared to Sema.
393
+ // LifetimeDependenceInfo from the swift decl. Reason for duplicated code is
394
+ // the apis on type and ownership is different in SIL compared to Sema.
383
395
std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::fromDependsOn (
384
396
LifetimeDependentTypeRepr *lifetimeDependentRepr, unsigned targetIndex,
385
397
ArrayRef<SILParameterInfo> params, DeclContext *dc) {
@@ -476,10 +488,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
476
488
// Infer self dependence for a mutating function with no result.
477
489
//
478
490
// FIXME: temporary hack until we have dependsOn(self: param) syntax.
479
- // Do not apply this to accessors (_modify). _modify is handled below like a
480
- // mutating method.
481
- if (fd->isMutating () && fd->getResultInterfaceType ()->isVoid ()
482
- && !dc->getSelfTypeInContext ()->isEscapable ()) {
491
+ // Do not apply this to accessors (_modify). _modify is handled below like
492
+ // a mutating method.
493
+ if (fd->isMutating () && fd->getResultInterfaceType ()->isVoid () &&
494
+ !dc->getSelfTypeInContext ()->isEscapable ()) {
483
495
return inferMutatingSelf (afd);
484
496
}
485
497
}
@@ -510,10 +522,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
510
522
Type selfTypeInContext = dc->getSelfTypeInContext ();
511
523
if (selfTypeInContext->isEscapable ()) {
512
524
if (isBitwiseCopyable (selfTypeInContext, ctx)) {
513
- diags.diagnose (
514
- returnLoc,
515
- diag::lifetime_dependence_method_escapable_bitwisecopyable_self);
516
- return std::nullopt;
525
+ diags.diagnose (
526
+ returnLoc,
527
+ diag::lifetime_dependence_method_escapable_bitwisecopyable_self);
528
+ return std::nullopt;
517
529
}
518
530
}
519
531
auto kind = getLifetimeDependenceKindFromType (selfTypeInContext);
0 commit comments