@@ -240,6 +240,112 @@ getLifetimeDependenceKind(LifetimeEntry specifier, AbstractFunctionDecl *afd,
240240 return lifetimeKind;
241241}
242242
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+
243349std::optional<LifetimeDependenceInfo>
244350LifetimeDependenceInfo::fromDependsOn (AbstractFunctionDecl *afd,
245351 TypeRepr *targetTypeRepr, Type targetType,
@@ -264,122 +370,28 @@ LifetimeDependenceInfo::fromDependsOn(AbstractFunctionDecl *afd,
264370 ? (afd->getParameters ()->size () + 1 )
265371 : afd->getParameters ()->size ();
266372
267- SmallBitVector inheritLifetimeParamIndices (capacity);
268- SmallBitVector scopeLifetimeParamIndices (capacity);
373+ SmallBitVector inheritIndices (capacity);
374+ SmallBitVector scopeIndices (capacity);
375+ bool isImmortal = false ;
376+ bool hasError = false ;
269377
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);
367381 }
368382
383+ if (hasError) {
384+ return std::nullopt ;
385+ }
369386 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);
378390}
379391
380392// 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.
383395std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::fromDependsOn (
384396 LifetimeDependentTypeRepr *lifetimeDependentRepr, unsigned targetIndex,
385397 ArrayRef<SILParameterInfo> params, DeclContext *dc) {
@@ -480,10 +492,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
480492 // Infer self dependence for a mutating function with no result.
481493 //
482494 // FIXME: temporary hack until we have dependsOn(self: param) syntax.
483- // Do not apply this to accessors (_modify). _modify is handled below like a
484- // mutating method.
485- if (fd->isMutating () && fd->getResultInterfaceType ()->isVoid ()
486- && !dc->getSelfTypeInContext ()->isEscapable ()) {
495+ // Do not apply this to accessors (_modify). _modify is handled below like
496+ // a mutating method.
497+ if (fd->isMutating () && fd->getResultInterfaceType ()->isVoid () &&
498+ !dc->getSelfTypeInContext ()->isEscapable ()) {
487499 return inferMutatingSelf (afd);
488500 }
489501 }
@@ -514,10 +526,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
514526 Type selfTypeInContext = dc->getSelfTypeInContext ();
515527 if (selfTypeInContext->isEscapable ()) {
516528 if (isBitwiseCopyable (selfTypeInContext, ctx)) {
517- diags.diagnose (
518- returnLoc,
519- diag::lifetime_dependence_method_escapable_bitwisecopyable_self);
520- return std::nullopt ;
529+ diags.diagnose (
530+ returnLoc,
531+ diag::lifetime_dependence_method_escapable_bitwisecopyable_self);
532+ return std::nullopt ;
521533 }
522534 }
523535 auto kind = getLifetimeDependenceKindFromType (selfTypeInContext);
0 commit comments