-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Remove the experimental LifetimeDependenceDiagnoseTrivial feature. #78283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Briefly, some versions of Span in the standard library violated trivial lifetimes; versions of the compiler built at that time simply ignored dependencies on trivial values. For now, disable trivial dependencies to allow newer compilers to build against those older standard libraries. This check is only relevant for ~6 mo (until July 2025).
CxxSpan is trivial, but not immortal. This initializer is diagnosed with an error after enabling trivial dependence enforcement. Correct this with an _overrideLifetime call. This could be avoided if we had a another way to tell the compiler that CxxSpan.__dataUnsafe() produced a pointer with the same effective lifetime as the CxxSpan.
A trivial value that is marked dependent on the access scope of another trivial variable is escaping of its use is outside the access scope.
This was never used to generate a .swiftinterface, so can be safely removed. It was used to guard compiler fixes that might break older .swiftinterface files. Now, we guard the same fixes by checking the source file type.
@Xazax-hun please take a look at the Span initializer fix |
@swift-ci test |
@swift-ci benchmark |
@Xazax-hun this appears to fix: rdar://136668965 (Borrow diagnostics not triggered for foreign types) |
This is wonderful news, thanks a lot for looking into it! |
@unsafe | ||
@lifetime(borrow span) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, I am not sure this would work for the purposes we want to use this conversion for.
The planned usage looks like this. imagine the following C++ function:
using SpanOfInt = std::span<int>;
SpanOfInt foo(const Bar& b [[clang::lifetimebound]]);
We plan to import it like this:
@_disfavoredOverload
func foo(b: borrwing Bar) -> SpanOfInt
And we plan to generate a safe wrapper using Swift's span something like this:
@lifetime(bar)
func foo(b: borrowing Bar) -> Span<int> {
Span(_unsafeCxxSpan: foo(b))
}
Note that, we expect the Swift span to be used after the lifetime of the corresponding C++ span ends. I'd expect this to be OK as the C++ span does not actually own the buffer. So we want to inherit/copy the dependencies of the C++ span to the Swift span. Unfortunately, we cannot do that as the C++ span is escapable. This is why my initial feeling was to just make the Swift span immortal and leave it to the safe wrapper to propagate the correct lifetimes.
What do you think, what would be the proper way to make this scenario work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Xazax-hun We have two options for ceating such wrappers:
- Add
@_unsafeNonescapableResult
to the Span initializer:
@_unsafeNonescapableResult
Span.init<T: CxxSpan<Element>>(_unsafeCxxSpan span: borrowing T)`
This is ok if you never expect programmers to access this initializer. You're placing the responsibilty for safety entirely on the wrapper.
- Add
_overrideLifetime
to the wrapper:
@lifetime(bar)
func foo(b: borrowing Bar) -> Span<int> {
let cxxSpan = cxx_foo(b)
let swiftSpan = Span(_unsafeCxxSpan: cxxSpan)
// The lexical variable scope of cxxSpan covers the final use if `swiftSpan` below:
return _overrideLifetime(swiftSpan, borrowing: b)
}
This was never used to generate a .swiftinterface, so can be safely removed. It
was used to guard compiler fixes that might break older .swiftinterface
files. Now, we guard the same fixes by checking the source file type.
This depends on fixing Span initialization from CxxSpan.