Skip to content

Disable surprising lifetime inference of implicit initializers #82472

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

Merged
merged 1 commit into from
Jun 27, 2025

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Jun 25, 2025

Non-escapable struct definitions often have inicidental integer fields that are
unrelated to lifetime. Without an explicit initializer, the compiler would infer
these fields to be borrowed by the implicit intializer.

struct CountedSpan: ~Escapable {
  let span: Span<Int>
  let i: Int

  /* infer: @lifetime(copy span, borrow i) init(...) */
}

This was done because

  • we always want to infer lifetimes of synthesized code if possible
  • inferring a borrow dependence is always conservative

But this was the wrong decision because it inevitabely results in lifetime
diagnostic errors elsewhere in the code that can't be tracked down at the use
site:

let span = CountedSpan(span: span, i: 3) // ERROR: span depends on the lifetime of this value

Instead, force the author of the data type to specify whether the type actually
depends on trivial fields or not. Such as:

struct CountedSpan: ~Escapable {
  let span: Span<Int>
  let i: Int

  @lifetime(copy span) init(...) { ... }
}

This fix enables stricter diagnostics, so we need it in 6.2.

Fixes rdar://152130977 ([nonescapable] confusing diagnostic message when a
synthesized initializer generates dependence on an Int parameter)

@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci test

@atrick atrick enabled auto-merge June 25, 2025 01:15
@atrick atrick requested a review from meg-gupta June 25, 2025 01:15
@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

Linux PR testing on main has been blocked all day

Miscellaneous_Plugins.aY4PdU/MySourceGenPlugin/Sources/MySourceGenBuildToolLib/library.swift:7: error: undefined reference to '$sSy10FoundationE20replacingOccurrences2of4with7options5rangeSSqd___qd_0_SS0A10EssentialsE14CompareOptionsVSnySS5IndexVGSgtSyRd__SyRd_0_r0_lF'

@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci smoke test linux

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci smoke test linux

Copy link
Contributor

@meg-gupta meg-gupta left a comment

Choose a reason for hiding this comment

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

LGTM.

Can you add a swift test for CountedSpan as well with your comments from the PR?

@atrick atrick disabled auto-merge June 25, 2025 18:33
@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

Can you add a swift test for CountedSpan as well with your comments from the PR?

I added a motivational example with explanation.

@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci smoke test

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci smoke test

@atrick atrick enabled auto-merge June 25, 2025 23:18
@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test windows

@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test macOS

@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

This PR used to pass testing but now keeps failing with

ObjectIdentifier+DebugDescription.swift:16:7: error: external macro implementation type 'SwiftMacros.DebugDescriptionMacro' could not be found for macro 'DebugDescription()'; plugin for module 'SwiftMacros' not found

@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test

@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test macOS

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test macOS

Non-escapable struct definitions often have inicidental integer fields that are
unrelated to lifetime. Without an explicit initializer, the compiler would infer
these fields to be borrowed by the implicit intializer.

    struct CountedSpan: ~Escapable {
      let span: Span<Int>
      let i: Int

      /* infer: @Lifetime(copy span, borrow i) init(...) */
    }

This was done because
- we always want to infer lifetimes of synthesized code if possible
- inferring a borrow dependence is always conservative

But this was the wrong decision because it inevitabely results in lifetime
diagnostic errors elsewhere in the code that can't be tracked down at the use
site:

    let span = CountedSpan(span: span, i: 3) // ERROR: span depends on the lifetime of this value

Instead, force the author of the data type to specify whether the type actually
depends on trivial fields or not. Such as:

    struct CountedSpan: ~Escapable {
      let span: Span<Int>
      let i: Int

      @Lifetime(copy span) init(...) { ... }
    }

This fix enables stricter diagnostics, so we need it in 6.2.

Fixes rdar://152130977 ([nonescapable] confusing diagnostic message when a
synthesized initializer generates dependence on an Int parameter)
@atrick
Copy link
Contributor Author

atrick commented Jun 26, 2025

@swift-ci smoke test

@atrick
Copy link
Contributor Author

atrick commented Jun 27, 2025

@swift-ci smoke test windows

1 similar comment
@atrick
Copy link
Contributor Author

atrick commented Jun 27, 2025

@swift-ci smoke test windows

@atrick atrick merged commit 5a86600 into swiftlang:main Jun 27, 2025
3 checks passed
@atrick atrick deleted the explicit-init branch June 27, 2025 22:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants