Skip to content

[6.2] Disable surprising lifetime inference of implicit initializers #82473

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 25, 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)

(cherry picked from commit 8789a68)

--- CCC ---

Explanation: Disable an inference rule that was unexpected and usually undesirable. See the discussion above.

Scope: This only affects users of the experimental feature: Lifetimes.

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

main PR: #82472

Risk: Low.

This may initially break some code that adopts Lifetimes, but only cases in which the code was not doing what the author
intended. This is a good source break. Failing to make this change now means much worse source breaking change in a
later release.

Testing: Added several source-level unit tests

Reviewer: Meghana Gupta

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)

(cherry picked from commit 8789a68)
@atrick atrick requested a review from a team as a code owner June 25, 2025 01:15
@atrick atrick added 🍒 release cherry pick Flag: Release branch cherry picks swift 6.2 labels Jun 25, 2025
@atrick atrick requested review from meg-gupta and tbkka June 25, 2025 01:16
@atrick
Copy link
Contributor Author

atrick commented Jun 25, 2025

@swift-ci test

@atrick atrick merged commit 54651d1 into swiftlang:release/6.2 Jun 25, 2025
5 checks passed
@atrick atrick deleted the 62-explicit-init branch June 25, 2025 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks swift 6.2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants