Skip to content
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

[cxx-interop] Document guarantees and assumptions for non-const C++ s… #816

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

fahadnayyar
Copy link

These assumptions and guarantees are important to be documented to make sure that when C++ Shared Reference Types are passed as a non-const parameter to a C++ function or method from swift, then user's don't make wrong assumptions about the default behaviour supported in the Swift compiler.

…hared references passed to a C++ API from Swift
@fahadnayyar
Copy link
Author

@swift-ci test

@@ -1271,6 +1271,20 @@ owned/guaranteed calling conventions. The C++ callers must guarantee that `x` is
Note that functions returning a shared reference type such as `returnSharedObject` transfer the ownership to the caller.
The C++ caller of this function is responsible for releasing the object.

If a C++ Shared Reference Type is passed as an argument to a C++ API from Swift, the Swift compiler *guarantees* that the passed value would be alive. Also Swift *assumes* that the C++ API is not consuming i.e., it returns with a valid object in the passed reference at the end of the C++ API call.
Copy link

@ravikandhadai ravikandhadai Sep 20, 2024

Choose a reason for hiding this comment

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

@fahadnayyar I would like to suggest these changes:

f a C++ Shared Reference Type is passed as an argument to a C++ API from Swift, the Swift compiler guarantees that the passed value would be alive.

Can we add the following after this sentence.
... guarantees that the passed value would be alive, and retains ownership of the value. In other words, the argument is passed as +0 and there is no transfer of ownership.

Also Swift assumes that the C++ API is not consuming i.e., it returns with a valid object in the passed reference at the end of the C++ API call.

Can we rephrase this as follows:
The C++ function is responsible for ensuring that the value pointed to by the parameter is alive during and at the end of the call. The C++ function should not assume it has ownership of the value and should do necessary retain operations if it is needs to take ownership.

If the argument is an inout (non-const reference) as shown below:

void takeSharedObjectAsInout(SharedObject *& x) { ... }

which would be imported in Swift as

func takeSharedObjectAsInout(_ x: inout SharedObject) { ... }

If the C++ function overwrites the value of the argument with the new value, it is responsible for releasing the old value, and ensuring that the new value is properly retained so that the Swift caller has ownership of the new value when the function returns. Adhering to these rules is necessary to safely and correctly pass around SWIFT_SHARED_REFERENCE between Swift and C++. These rules are also generally recommended conventions to manage shared objects that use reference counting.

@@ -1271,6 +1271,20 @@ owned/guaranteed calling conventions. The C++ callers must guarantee that `x` is
Note that functions returning a shared reference type such as `returnSharedObject` transfer the ownership to the caller.
The C++ caller of this function is responsible for releasing the object.

If a C++ Shared Reference Type is passed as an argument to a C++ API from Swift, the Swift compiler *guarantees* that the passed value would be alive. Also Swift *assumes* that the C++ API is not consuming i.e., it returns with a valid object in the passed reference at the end of the C++ API call.
Copy link
Contributor

Choose a reason for hiding this comment

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

I have a few comments on the wording and formatting:

  1. The rest of this document doesn't capitalize "C++ reference types", I think it's better to be consistent here.
  2. I think it's better not to use bold highlighting for *guarantees*/*assumes*, the rest of the document doesn't use it, and I feel that it attracts too much attention.
  3. Minor: the comma , usually goes before i.e., could you please swap them?
  4. I don't have a strong opinion, but to me "function call" sounds better than "API call", since to me API means a collection of functions, types, etc.


```swift
var obj = SharedObject.create()
receiveSharedObject(obj) // Swift gaurantees that obj is alive
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: guarantees

receiveSharedObject(obj) // Swift gaurantees that obj is alive
```

```c++
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for explicitly specifying the language for code blocks! 👍

@shahmishal
Copy link
Member

@egorzhdan @fahadnayyar Is this PR ready to be merged?

@egorzhdan
Copy link
Contributor

@shahmishal no, not yet.

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.

4 participants