Skip to content

Compile-time lifetime dependency annotations#3145

Open
atrick wants to merge 2 commits intoswiftlang:mainfrom
atrick:lifetime-dependency
Open

Compile-time lifetime dependency annotations#3145
atrick wants to merge 2 commits intoswiftlang:mainfrom
atrick:lifetime-dependency

Conversation

@atrick
Copy link
Contributor

@atrick atrick commented Feb 25, 2026

Propose a @lifetime attribute to explicitly annotate declarations that produce non-Escapable values.

This proposal is also intended to serve as documentation of the state of the compiler implementation of the experimental Lifetimes feature for early adopters.

Previous proposal: #2750

@atrick atrick changed the title Consolidate, update, and expand the lifetime dependency proposal Compile-time Lifetime Dependency Annotations Feb 25, 2026
- Incorporate content from previous pitches
- Reorganize proposal structure and flow
- Add sections covering implicit defaults, closures, and lifetime requirements
@atrick atrick force-pushed the lifetime-dependency branch from de61433 to 1ad4fd1 Compare February 25, 2026 05:06
@atrick atrick changed the title Compile-time Lifetime Dependency Annotations Compile-time lifetime dependency annotations Feb 25, 2026
In addition to function declarations, function types must support lifetime annotations so functions that return non-`Escapable` types can be passed as closures.

```
func foo(closure: @lifetime(borrow arg) (_ arg: Container) -> Span<T>) { ... }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be @_lifetime instead of @lifetime. Other examples need to be updated as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a proposal for the non-underscored syntax, so all the @_lifetime have been changed to @lifetime.

Of course, that's confusing to adopters using this as documentation. So maybe this should be explained in the introduction?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If adopters are using examples listed here to experiment, they may see confusing errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal now mentions that the current implementation uses underscore. I believe adopters will get this warning
warning: Unsupported use of @lifetime, use @_lifetime to specify lifetime dependencies

Copy link

@Xazax-hun Xazax-hun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked at the detailed design yet, but have some questions inline.


The `borrow` or `&` dependency specifiers indicate a scoped dependency on the argument. A scoped dependency must correspond to the argument's ownership:

* A `borrow` dependency specifier requires `borrowing` ownership. It extends borrowing access, prohibiting mutations of the argument, but allowing other simultaneous borrowing accesses.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If borrow and & can only be used with one parameter convention, does that mean we have some redundancy in the syntax and we could get rid of some tokens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the redundancy is intentional (in fact we added it later). We don't want the syntax to indicate that a mutable value is being "borrowed", as in @_lifetime(borrow x), because that normally implies a read-only shared borrow. The lifetime dependency only cares that there is either an immutable or mutable access scope, but programmers always think in terms of the parameter's ownership borrowing or inout.

An `inout` parameter that is conditionally reassigned has two dependency sources:

```swift
@lifetime(span: copy span, copy another)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the syntax disambiguated when we also have a return type?
I.e., how the annotation would look like for:

func mayReassign(span: inout Span<Int>, to another: Span<Int>) -> Span<Int> {
  span = (...) ? span : another
  return another
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are we missing a span: after the comma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each target uses a separate @_lifetime attribute because they're really unrelated, so the target is only written once:
@lifetime(target: source1, source2)
I can see how that's confusing. hopefully the grammar makes it clear. This example is:

@lifetime(span: /*span ,*/ another)
@lifetime(span, another) // if the result can be copied from either parameter
func mayReassign(span: inout Span<Int>, to another: Span<Int>) -> Span<Int> {


```swift
struct Wrapper<Element: ~Escapable>: ~Escapable {
var element: Element {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we require these lifetime annotations? Shouldn't these follow from substituting the generic argument for Element in generic code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the lifetime attributes in that example are all the defaults. That's mentioned just below the example. I added a comment to the example too.

_ = span
```

In the future, with additional syntax support, it may be possible for a function type to express dependenies simultaneously on both the closure value and its parameters. See "Closure capture dependency syntax".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when a closure captures a Span or a MutableSpan? Does that have any implications on the escapability, copyability or any other properties of the closure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The future direction "Fine-grained closure capture dependencies" has an example of a closure capturing a Span. It doesn't change much other than loosen the lifetime restriction on the captured value... the closure's result could outlive the captured span, as long as it doesn't outlive that span's dependency (the container that gave you the span)

@Web4application
Copy link

I hope all this is not from my device and if it is , or even if it’s another developer, you are tracking and updating privately without the person consent, is this how all of you do ? So most of this software was stolen and claimed. Anyway if this is from my database , stop it or I shut it down myself ,
Compensation for that developer who broke the barrier isn’t bad ? You all have enough , Atleast he deserves something
I this is from me , been long I detected the changes tho.
You can’t just sit waiting for an update from someone who’s working 24/7 on a research after getting it you all take the glory ,
Something must be done to all these

@rjmccall rjmccall added LSG Contains topics under the domain of the Language Steering Group new proposal Adds a new proposal document labels Mar 2, 2026
@xwu xwu mentioned this pull request Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LSG Contains topics under the domain of the Language Steering Group new proposal Adds a new proposal document

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants