Commit Graph

81 Commits

Author SHA1 Message Date
Michael Gottesman
80ce07ca66 [silgen] Teach SILGen how to emit a forced dynamic member ref given nonisolated(nonsending) casts.
Specifically, I taught SILGen how to emit an AST like the following:

```
(force_value_expr implicit type="nonisolated(nonsending) (Date?) async -> Void" implicit_iuo_unwrap
  (open_existential_expr implicit type="(nonisolated(nonsending) (Date?) async  -> Void)?"
    (opaque_value_expr implicit type="AnyObject")
    (declref_expr type="AnyObject" decl="test.(file).repro().anyObject@test.swift:6:7" function_ref=unapplied)
    (optional_evaluation_expr type="(nonisolated(nonsending) (Date?) async -> Void)?"
      (inject_into_optional type="(nonisolated(nonsending) (Date?) async -> Void)?"
        (function_conversion_expr type="nonisolated(nonsending) (Date?) async -> Void"
          (bind_optional_expr type="(Date?) async -> Void" depth=0
            (dynamic_member_ref_expr type="((Date?) async -> Void)?" decl="__ObjC.(file).Foo.start(at:)"
              (opaque_value_expr type="AnyObject"))))))))
```

Since we are emitting an objc async function, there isn't an extra implicit
parameter like if we were using a swift async function. So, I just reused code
that was already used locally to look through these sorts of conversions. I
just had to add to that code support for conversions that add
nonisolated(nonsending). Previously it only supported looking through global
actor conversions.

rdar://152596823
(cherry picked from commit 662dbdb55a)
2025-06-06 23:34:40 -04:00
Michael Gottesman
0d519a1acb [sema] Change non-sendable -> non-Sendable in diagnostics.
This matches send non sendable but importantly also makes it clear that we are
talking about something that doesn't conform to the Sendable protocol which is
capitalized.

rdar://151802975
(cherry picked from commit 3ed4059a60)
2025-05-23 10:31:05 -07:00
Michael Gottesman
03d8c0ae6b [concurrency] Ensure that we treat closures that are nonisolated(nonsending) via their ActorIsolation as nonisolated(nonsending).
Some notes:

1. In most cases, I think we were getting lucky with this by just inferring the
closure's isolation from its decl context. In the specific case that we were
looking at here, this was not true since we are returning from an @concurrent
async function a nonisolated(nonsending) method that closes over self. This
occurs since even when NonisolatedNonsendingByDefault we want to start importing
objc async functions as nonisolated(nonsending).

2. I also discovered that in the ActorIsolationChecker we were not visiting the
inner autoclosure meaning that we never set the ActorIsolation field on the
closure. After some discussion with @xedin about potentially visiting the
function in the ActorIsolationChecker, we came to the conclusion that this was
likely to result in source stability changes. So we put in a targeted fix just
for autoclosures in this specific case by setting their actor isolation in the
type checker.

3. Beyond adding tests to objc_async_from_swift to make sure that when
NonisolatedNonsendingByDefault is disabled we do the right thing, I noticed that
we did not have any tests that actually tested the behavior around
objc_async_from_swift when NonisolatedNonsendingByDefault is enabled. So I added
the relevant test lines so we can be sure that we get correct behavior in such a
case.

rdar://150209093
(cherry picked from commit ced96aa5cd)
2025-05-07 13:03:45 -07:00
John McCall
e9ebc7c848 Pass a zero normal result to ObjC async completion handlers on the error path.
Fixes #65199
2025-03-26 00:58:27 -04:00
Gabor Horvath
6d24c52b80 [cxx-interop] Use the locations imported from C++
A recent PR (#77204) started to import C++ source locations into Swift.
This PR flips a switch so these locations are actually used more widely.
Now some of the diagnostic locations are changed, but they generally
improved the quality of the diagnostics, pointing out conformances
imported from Obj-C code right when they are declared.
2024-11-01 13:49:09 +00:00
Allan Shortlidge
5bdd952792 Tests: More test coverage in objc_async_conformance.swift
Add regression tests for rdar://125945942.
2024-04-09 15:20:18 -07:00
Allan Shortlidge
8a27b681b0 Tests: Increase test coverage in objc_async_conformance.swift.
Add regression tests for rdar://125935350.
2024-04-09 15:20:18 -07:00
Allan Shortlidge
e057b686a5 Sema: Effectively revert https://github.com/apple/swift/pull/70569.
The fix caused a source break that is now captured as an additional test case
in `objc_async_conformance.swift`.

Resolves rdar://121527977
2024-02-20 22:54:33 -08:00
nate-chandler
bf50e2f81b Merge pull request #70729 from nate-chandler/rdar119732084
[SILGen] Fix leak in thunk for async throwing swift conformance to ObjC requirement with optional completion.
2024-01-05 00:37:33 -08:00
Nate Chandler
9f5a7c87c3 [SILGen] Fix leak in objc async thunk.
Fix a leak when emitting the native to foreign thunk for an async
function which fulfills an Objective-C protocol requirement which can be
fulfilled with either a value or an error via a nullable completion.

Previously, the SIL in question used to look like this:

```sil
  %maybe_completion = ...
  try_apply %impl..., normal success, ...

success(%value):
  switch_enum %maybe_completion...
      case some!enumelt: invoke
      case none!enumelt: ignore

ignore:
  br join

invoke(%completion):
  %some_value = enum Optional, some!enumelt, %value // consumes %value
  %guaranteed_some_value = begin_borrow %some_value
  %none_error = enum Optional, none!enumelt
  apply %completion(%guaranteed_some_value, %none_error)
  end_borrow %guaranteed_some_value
  destroy_value %some_value
  br join

join:
  destroy_value %maybe_completion
  ...
```

which leaks %value on the codepath through `ignore`.

Note that `%value` is consumed by the `enum` instruction, but
`%completion` is invoked with `%guaranteed_some_value`, a guaranteed
value.  So there is no need to consume %value in `invoke`.

Here, `%value` itself is borrowed and forwarded into an enum instruction
whose result is passed to `%completion`:

```sil
  %maybe_completion = ...
  try_apply %impl..., normal success, ...

success(%value):
  switch_enum %maybe_completion...
      case some!enumelt: invoke
      case none!enumelt: ignore

ignore:
  br join

invoke(%completion):
  %guaranteed_value = begin_borrow %value
  %guaranteed_some_value = enum Optional, some!enumelt, %guaranteed_value
  %none_error = enum Optional, none!enumelt
  apply %completion(%guaranteed_some_value, %none_error)
  end_borrow %guaranteed_some_value
  br join

join:
  destroy_value %maybe_completion
  destroy_value %value
  ...
```

Because an argument scope was already being created and a cleanup was
already being pushed for `%value`, nothing more is required to fix the
issue than to reorder the enum and the borrow.

rdar://119732084
2024-01-04 19:10:17 -08:00
Kavon Farvardin
06ac850d74 [SILGen] avoid hop before autoreleased foreign error is retained
For an isolated ObjC function that is not async, we
emit a hops around the call. But if that function
returns an autoreleased pointer, we need to ensure
we're retaining that pointer before hopping back
after the call. We weren't doing that in the case
of an autoreleased NSError:

```
%10 = alloc_stack $@sil_unmanaged Optional<NSError>
%19 = ... a bunch of steps to wrap up %10 ...
%20 = enum $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, #Optional.some!enumelt, %19 : $AutoreleasingUnsafeMutablePointer<Optional<NSError>>
hop_to_executor $MainActor
%26 = apply X(Y, %20) : $@convention(objc_method) (NSObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>) -> @autoreleased Optional<NSString>
hop_to_executor $Optional<Builtin.Executor>
// retain the autoreleased pointer written-out.
%28 = load [trivial] %10 : $*@sil_unmanaged Optional<NSError>
%29 = unmanaged_to_ref %28 : $@sil_unmanaged Optional<NSError> to $Optional<NSError>
%30 = copy_value %29 : $Optional<NSError>
assign %31 to %7 : $*Optional<NSError>
```

This patch sinks the hop emission after the call
so it happens after doing that copy.

rdar://114049646
2023-12-19 13:16:59 -08:00
Pavel Yaskevich
ab4f8d0dc0 [RequirementMachine] Inherited requirements collection should account for synthesized protocols
ClangImporter adds `SynthesizedProtocolAttr` to model inheritance
from `Sendable` on protocols imported from Objective-C.
2023-11-16 10:58:34 -08:00
Holly Borla
57214ce7fb [Concurrency] Try harder to downgrade preconcurrency errors to warnings in
Swift 5 mode.

When you annotate a ValueDecl with `@preconcurrency`, the compiler should allow
concurrency violations by downgrading errors in the actor isolation checker to
warnings in Swift 5 mode. Previously, the actor isolation checker only checked
whether the caller's context was preconcurrency when deciding to downgrade, so
referencing preconcurrency declarations directly remained errors. Preconcurrency
was also dropped when computing actor isolation for declarations imported from
clang, which are always preconcurrency.
2023-10-04 07:07:41 -07:00
Kavon Farvardin
4fcc58a3fe test coverage for rdar://97646309 2022-08-10 12:50:01 -07:00
Kavon Farvardin
814fb42554 fix nested suspension issue with objc async calls
when two objc async functions are composed with each other,
i.e., f(g()), then the clean-ups for g() would get emitted
at an unexpected time, namely, during the suspension for
the call to f(). This means that using a clean-up to emit
the executor-hop breadcrumb was incorrect. The hop could
appear between a get_async continuation and its matching
await_continuation, which is an unsupported nested suspension.

This commit fixes that by removing the use of the breadcrumb
clean-up in favor of providing that breadcrumb directly to
the result plan, so that it may be emitted later on when the
result plan sees fit.

Fixes rdar://91502776
2022-05-02 18:20:59 -07:00
Doug Gregor
9df6394afe [Clang importer] Consider attributes on the typedef name for an anonymous tag.
In C, one can provide a typedef name for an anonymous tag declaration in
one shot, e.g.,

    typedef struct {
      double x, y
    } Point;

In this case, there are effectively two declarations at the C level:
the typedef and the struct. The Clang importer was only taking
attributes from the anonymous struct (i.e., the tag) and not from the
typedef. However, any attributes put before the `typedef` should apply
as well... so consider those, too.

For now, only do this for `swift_attr` attributes, because we're
seeing this primarily with `Sendable` annotations. In the future, we
can look to generalizing it, but that could have source-breaking
consequences.

Fixes rdar://91632960.
2022-04-22 17:40:13 -07:00
Becca Royal-Gordon
a57e71ccd0 Import swift_attr(“@Sendable”) for result types
If `__attribute__((swift_attr(“@Sendable”)))` is applied to an ObjC method, ObjC property, C field, C variable, or C function, we will now make its result type `Sendable`.

For some entities, this technically had a different behavior previously, because `@Sendable` can be applied to `func`s to indicate that their interface type should be `@Sendable`. We don’t really want people to use this functionality on non-local functions, so we can safely remove it.

This isn’t quite interacting with `Unmanaged` the way we’d want, but I’ve included test cases for the current behavior with FIXME comments.

Fixes rdar://90491024.
2022-03-29 17:18:10 -07:00
Becca Royal-Gordon
51e5408eeb [ClangImporter] Allow @Sendable on more params
When `__attribute__((swift_attr(“@Sendable”)))` is applied to a clang parameter Swift now attempts to make the type `Sendable` in a more comprehensive way than before:

* If it is a function type, it adds `@Sendable` to it.
* If it is a protocol composition type, it adds `& Sendable` to it.
* If it is a class, protocol, or generic class, it inserts it into a protocol composition and adds `& Sendable`.
* If it is a typealias, it *may* desugar it to a modified version of the underlying type.
* In various other cases, it recurses into the children of the type.

This allows Objective-C methods and functions to require that their arguments have a Sendable type without specifying a particular type they must belong to.

Fixes rdar://87727549.
2022-03-10 16:03:37 -08:00
Kavon Farvardin
3c04f0a9f4 [SR-15694] make isolation inference + override more consistent
During actor isolation inference, we would unconditionally choose the
isolation of the overridden decl (when, say, there is no attribute on the decl).
The overridden decl is identified with `getOverriddenDecl`.

This works mostly fine, but initializers have some unusual overridden decls
returned by that method. For example, in the following code:

```swift
@objc class PictureFrame: NSObject {
  init(size: Int) { }
}

@MainActor
class FooFrame: PictureFrame {
  init() {
    super.init(size: 0)
  }
}
```

that method claims that `FooFrame.init()` overrides `PictureFrame.init()`, when
it really does not! So, if we were to unconditionally take the isolation from
`PictureFrame.init()` (and thus `NSObject.init()`), then we'd infer that
`FooFrame.init()` has unspecified isolation, despite the nominal it resides in
being marked as `MainActor`. This is in essence the problem in SR-15694, where
placing the isolation directly on the initializer fixes this issue.

If `FooFrame.init()` really does override, then why can it be `MainActor`? Well,
we have a rule in one part of the type-checker saying that if an ObjC-imported
decl has unspecified isolation, then overriding it with isolation is permitted.
But the other part of the type-checker dealing with the isolation inference was
not permitting that.

So, this patch unifies how actor-isolation inference is conducted to reuse that
same logic. In addition, the inference now effectively says that, if the decl
has no inferred isolation, or the inferred isolation is invalid according to the
overriding rules, then we use the isolation of the overridden decl. This
preserves the old behavior of the inference, while also fixing this issue with
ObjC declarations by expanding where isolation is allowed.

For example, as a consequence of this change, in the following code:

```swift
@MainActor
class FooFrame: NotIsolatedPictureFrame {
  override func rotate() {
    mainActorFn()
  }
}
```

if `NotIsolatedPictureFrame` is a plain-old not-isolated class imported from
Objective-C, then `rotate` will now have `MainActor` isolation, instead of
having unspecified isolation like it was inferred to have previously. This
helps make things consistent, because `rotate` is allowed to be `@MainActor` if
it were explicitly marked as such.

resolves rdar://87217618 / SR-15694
2022-03-07 16:41:43 -07:00
Becca Royal-Gordon
8c844126d4 [ClangImporter] Make completion handlers Sendable
If a method has an `async` variant, the non-`async` variant will now mark its completion handler parameter `@Sendable`. This shouldn't be a breaking change in Swift 5 code since these declarations are automatically `@_predatesConcurrency`.

Also adds:

• Support for `@_nonSendable` on parameters, which can be used to override this implicit `@Sendable`
• Support for `@Sendable` on block typedefs; it's generally going to be a good idea to mark completion block typedefs `@Sendable`.

Fixes rdar://85569247.
2022-01-25 15:49:54 -08:00
Evan Wilde
3a13721eae Add optional message to unavailablefromasync
Adding the ability to add an optional message to the unavailable from
async attribute. This can be used to indicate other possible API to use,
or help explain why it's unavailable.
2021-12-08 09:39:24 -08:00
Evan Wilde
694fad4aef Adding unavailableFromAsync tests
This patch adds a bunch of tests to verify the behaviour of the
@_unavailableFromAsync attribute.

The attribute is only allowed on functions, so we verify that an error
is emitted when it is applied to structs, extensions, classes, and
actors. The attribute may be applied to constructors to disallow
construction in an async context, but cannot be applied to destructors
since a destructor must be callable from anywhere. Additionally, the
attribute cannot be applied to asynchronous functions since an async
function _must_ be called from an async context.

Specific checks include
 - Errors are emitted in an async context (global function, e.g.)
 - Errors are emitted when the async context is nested in a sync context
 - Errors are not emitted from a sync context nested in an async context

This patch also includes verification that the attribute is propagated
across module boundaries and is be imported from ObjC functions.

Lastly, this patch adds the IDE completion testing to verify that the
attribute is considered.
2021-11-30 14:20:21 -08:00
Doug Gregor
16f32fd50a Eliminate support for @MainActor(unsafe) Clang attribute.
The `@MainActor(unsafe)` attribute could be provided for C declarations
via the Clang `swift_attr` attribute. However, this facility was never
used outside of tests, and has been superceded by `@MainActor` with the
inferred `@_predatesConcurrency`.
2021-11-29 15:05:18 -08:00
Doug Gregor
0c9c8f92c9 Imported C declarations always predate concurrency 2021-11-29 15:03:33 -08:00
Becca Royal-Gordon
ad0e7096ba Make NS_ENUM &c. Sendable even when audited
An explicit swift_attr("@_nonSendable") will override it (except for ns_error_domain where the type is embedded in another type that's forced to be Sendable), but swift_attr("@_nonSendable(_assumed)") will not.
2021-11-19 11:34:02 -08:00
Becca Royal-Gordon
b9480f12d0 Allow imported types to add a Sendable conformance
...by using `__attribute__((swift_attr("@Sendable")))`. `@_nonSendable` will "beat" `@Sendable`, while `@_nonSendable(_assumed)` will not.

This commit also checks if `SwiftAttr` supports `#pragma clang attribute` and, if it does, defines `__SWIFT_ATTR_SUPPORTS_SENDABLE_DECLS` in imported headers so they know they can apply these attributes in an auditing style.
2021-11-19 11:34:01 -08:00
Saleem Abdulrasool
4d44953691 Revert "Support __available__((swift_attr("@Sendable")))" 2021-11-19 07:40:24 -08:00
Becca Royal-Gordon
3d2d4e1721 Merge pull request #40170 from beccadax/send-me-an-object
Support __available__((swift_attr("@Sendable")))
2021-11-19 01:26:10 -08:00
Doug Gregor
a77f05f627 Switch @_unsafeSendable and @_unsafeMainActor tests to @_predatesConcurrency 2021-11-18 09:01:31 -08:00
Becca Royal-Gordon
8751658f6c Make NS_ENUM &c. Sendable even when audited
An explicit swift_attr("@_nonSendable") will override it (except for ns_error_domain where the type is embedded in another type that's forced to be Sendable), but swift_attr("@_nonSendable(_assumed)") will not.
2021-11-12 23:13:29 -08:00
Becca Royal-Gordon
7549278314 Allow imported types to add a Sendable conformance
...by using `__attribute__((swift_attr("@Sendable")))`. `@_nonSendable` will "beat" `@Sendable`, while `@_nonSendable(_assumed)` will not.

This commit also checks if `SwiftAttr` supports `#pragma clang attribute` and, if it does, defines `__SWIFT_ATTR_SUPPORTS_SENDABLE_DECLS` in imported headers so they know they can apply these attributes in an auditing style.
2021-11-12 23:13:29 -08:00
Nate Chandler
03e175a13e [Test] Added for call-as-async Optional<NS_EXTENSIBLE_STRING_ENUM>.
The underlying problem was fixed by the change for rdar://81590807 .
Add tests for the specific case that was originally reported.

rdar://80704382
2021-08-09 19:06:21 -07:00
Nate Chandler
6eb4f2ca8a [SILGen] Handled transforming Bridged? -> Swift.
Previously, the function emitCBridgedToNativeValue handled three
situations around optionals:
- Bridged?, Native?
- Bridged, Native?
- Bridged, Native

Here, handling for the fourth case
- Bridged?, Native
is added.

To enable this, the number of Optional wrappings that the bridged type
has that the native type does not is passed in to the function.  Then,
in the portions of the function where actual transformations are done,
the values are unwrapped an appropriate number of times.  Mostly that
means force unwrapping N times before doing the transformation.  In the
case of types that conform to _ObjectiveCBridgeable, however, it means
force unwrapping the value N-1 times after doing the transformation
because _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC
performs one layer of unwrapping itself.

rdar://81590807
2021-08-09 19:02:27 -07:00
Doug Gregor
38de7cc198 Allow async import of Objective-C methods with non-prototyped completion handler blocks.
We allow import of non-prototyped blocks such as `void (^)()` and treat
them the same way as `void (^)(void)`, so do the same with `async` imports.

Fixes rdar://81239857.
2021-08-05 17:53:33 -07:00
Nate Chandler
c493632b68 [SILGen] Used type AbstractionPattern.
Previously, AbstractionPattern::getOpaque() was used for async
continuations.  That was problematic for functions like

```objc
- (void)performVoid2VoidWithCompletion:(void (^ _Nonnull)(void (^ _Nonnull)(void)))completion;
```

whose completion takes a closure.  Doing so resulted in attempting to
build a block to func thunk where one of the functions had an out
parameter.

Instead, use the AbstractionPattern(ty).

rdar://79383990
2021-07-24 14:25:27 -07:00
Doug Gregor
6ba26292b1 [Clang importer] Import Swift declaration modifiers from swift_attr.
In addition to importing Swift attributes spelled with the C
`__attribute__((swift_attr("...")))`, also import declaration modifiers,
including `nonisolated`.

Fixes rdar://79402200.
2021-06-17 10:25:42 -07:00
Doug Gregor
2b9ca315fe [Concurrency] Remove asyncHandler attribute.
The `asyncHandler` attribute turned out to be the wrong solution
to the problem of creating a sync->async bridge. Remove it.
2021-05-13 17:01:39 -07:00
Doug Gregor
bf30b41e5b [Clang importer] Fix mirroring of protocol decls for 'async' imports.
The de-duplication checks to preventing redundant mirroring of protocol
declarations failed to consider that a given method could be
implemented as both 'async' and non-'async' declarations, and
therefore would fail to mirror the 'async' form. Account for this
distinction.

Fixes rdar://76799297.
2021-04-30 01:05:03 -07:00
Kavon Farvardin
64f6182cc7 prevent double @MainActor annotation in ClangImporter
This can lead to latent type errors for API users,
because a swiftmodule would otherwise be emitted,
without any diagnostics, containing imported decl
with two global actor annotations on it. Such
decls will always be an error to the typechecker
when its eventually encountered.

This patch drops all `@MainActor` annotations after
the first one in the ClangImporter, regardless of
whether its the safe or unsafe version, and emits
a warning when doing so.
2021-03-31 17:11:45 -07:00
Doug Gregor
f02a01e4f2 Add @_unsafeMainActor corresponding to @MainActor 2021-03-31 09:40:41 -07:00
Doug Gregor
ed7372b92b [Clang importer] Import @_unsafeSendable on C function/ObjC method params 2021-03-31 09:40:04 -07:00
Ben Barham
3de83aca66 [ClangImporter] Add @completionHandlerAsync for imported decls
Implicitly add the @completionHandlerAsync attribute for ObjCMethodDecl
that have a completion handler. Adds a link from the non-async to the
async function for use in diagnostics and refactorings.

Resolves rdar://74665226
2021-03-31 08:39:12 +10:00
Doug Gregor
45d3c8813c [Clang importer] Import __swift_attr__("@Sendable") as Sendable on parameters. 2021-03-24 22:35:09 -07:00
Doug Gregor
5f71e52146 [Clang import] Apply main-thread annotations from parameters to types.
Import a main-thread annotation on a function/method parameter in
(Objective-)C as a `@MainActor` function type.
2021-03-24 22:28:29 -07:00
Doug Gregor
74affffcb7 Propagate actor isolation freely through Objective-C declarations. 2021-03-04 22:49:57 -08:00
Joe Groff
4bb49ba521 SILGen/ClangImporter: Handle async imports with a boolean error flag argument.
Import APIs with the `swift_async_error` attribute in `zero_argument` or `nonzero_argument`
modes by checking the corresponding boolean argument to indicate the error status, instead of
treating it as part of the result tuple. rdar://70594666
2021-02-19 17:31:09 -08:00
Joe Groff
eea3a6c27f SILGen: Handle pseudogeneric completion-handler-based async APIs.
Plumb generic signatures through the codegen for invoking foreign APIs as async, so that we
correctly handle APIs declared on ObjC lightweight generic classes. rdar://74361267
2021-02-16 16:05:04 -08:00
Doug Gregor
a8f91c4efa [Clang importer] Allow @UIActor as an alias for @MainActor.
We've flip-flopped on the name a bit. Accept both for now.
2021-02-15 15:29:46 -08:00
Doug Gregor
71e0b1d90c [Clang importer] Don't suppress properties due to async method imports.
The Clang importer had some logic to suppress the import of a property that
had the same name as a method with no parameters. This logic
inadvertently meant that an async import of a completion-handler method
could prevent a (non-async) property of the same name to not be
imported, breaking existing code. In such cases, don't suppress the
property import.

Fixes rdar://73326019.
2021-02-12 13:19:16 -08:00
Kavon Farvardin
9318a24cbc Merge pull request #35859 from kavon/objc-async-import-extended-coverage
[concurrency][nfc] more test coverage for ObjC async conformance
2021-02-09 20:05:10 -08:00