Skip to content

Conversation

susmonteiro
Copy link
Contributor

@susmonteiro susmonteiro commented Aug 28, 2025

When we tried to create a std::optional of a nonescapable type in Swift, the compiler would run into an assertion failure. This is because std::optional has an anonymous union where one of its members would be of this nonescapable type.

Turns out that we were not handling anonymous unions with nonescapable members correctly. Fields of anonymous unions are injected to the parent as IndirectFieldDecl, so we need to handle these indirect fields the same way we handle "normal" fields.

rdar://156704699

@susmonteiro
Copy link
Contributor Author

@swift-ci please smoke test

@susmonteiro susmonteiro force-pushed the nonescapable-std-optional branch from ed52618 to bae381f Compare August 29, 2025 15:12
@susmonteiro
Copy link
Contributor Author

@swift-ci please smoke test

@susmonteiro susmonteiro force-pushed the nonescapable-std-optional branch from bae381f to 1bea41b Compare September 1, 2025 08:44
@susmonteiro
Copy link
Contributor Author

@swift-ci please smoke test


auto *vd = cast<VarDecl>(member);
if (!isNonEscapable) {
if (const auto *fd = dyn_cast<clang::FieldDecl>(nd))
Copy link
Contributor

Choose a reason for hiding this comment

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

Non-escapable is viral to the parents, so we should expect the parent record to be non-escapable when an indirect field is non-escapable. Would doing the same thing for both direct and indirect fields run into problems?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point, thanks. We can do the same thing for indirect fields by assuming that an anonymous union/struct can never be escapable, and thus we can compare the escapability of these indirect fields directly with the outer record (i.e. skipping the comparison with the anonymous record)

@susmonteiro susmonteiro force-pushed the nonescapable-std-optional branch from 1bea41b to d0ec83c Compare September 1, 2025 16:42
@susmonteiro susmonteiro force-pushed the nonescapable-std-optional branch from d0ec83c to 1bfa16a Compare September 1, 2025 16:51
@susmonteiro
Copy link
Contributor Author

@swift-ci please smoke test

Copy link
Contributor

@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.

LG, thanks!

@susmonteiro susmonteiro merged commit 6e56c24 into swiftlang:main Sep 2, 2025
3 checks passed
}

// CHECK: error: a function with a ~Escapable result needs a parameter to depend on
// CHECK-NO-LIFETIMES: test.swift:11:32: error: a function cannot return a ~Escapable result
Copy link
Contributor

Choose a reason for hiding this comment

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

@susmonteiro

You can make these line numbers resilient to this type of cascading change using:

// CHECK-NO-LIFETIMES: test.swift:[[@LINE+1]]:32: error: a function cannot return a ~Escapable result

By default this would be broken by split-files if you use FileCheck %s, since the line numbers change. This can be resolved by either using Filecheck %t/test.swift, or calling split-files --leading-lines which pads each file to preserve line numbers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh interesting, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ interop Feature: Interoperability with C++

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants