Skip to content

[cxx-interop] Add documentation about calling ctor or static factory of SWIFT_SHARED_REFERENCE types as Swift Initializer #1079

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

fahadnayyar
Copy link

Update C++ interop documentation to describe Swift initializer support for C++ SWIFT_SHARED_REFERENCE type's constructors and static factories annotated with SWIFT_NAME.

@fahadnayyar fahadnayyar marked this pull request as ready for review June 11, 2025 01:03
…of SWIFT_SHARED_REFERENCE types as Swift Initializer
@fahadnayyar fahadnayyar force-pushed the cxx-frt-ctor-static-factory-docs branch from b8a4ffc to d61979c Compare June 11, 2025 04:31
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.

object.doSomething()
// `object` will be released here.
```

You can create instances of `SharedObject` directly in Swift by calling its C++ constructor through a Swift initializer.

Alternatively, you can construct instances using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function
Copy link
Contributor

Choose a reason for hiding this comment

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

We should have a code example for this SWIFT_NAME trick. Also we should explain why would the user want to do this (e.g., we don't support custom allocators).

I think it is worth mentioning that we use the default new/delete for allocation/deallocation and if someone wants to disable the importing of ctors as initializers they can delete these operations for their class.

Copy link
Author

@fahadnayyar fahadnayyar Jul 1, 2025

Choose a reason for hiding this comment

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

Also we should explain why would the user want to do this (e.g., we don't support custom allocators).

Do we want to list all the reasons why user would want to SWIFT_NAME trick in this documentation?

Copy link
Author

Choose a reason for hiding this comment

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

think it is worth mentioning that we use the default new/delete for allocation/deallocation and if someone wants to disable the importing of ctors as initializers they can delete these operations for their class.

Updated the patch with these changes.

@fahadnayyar
Copy link
Author

CC: @j-hui
If you can also please take a look.

@fahadnayyar
Copy link
Author

CC: @ravikandhadai

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.

**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.
Copy link
Author

Choose a reason for hiding this comment

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

Need to change this into Note that

@@ -1250,11 +1250,41 @@ void releaseSharedObject(SharedObject *);

Now that `SharedObject` is imported as a reference type in Swift, the programmer will be able to use it in the following manner:
```swift
let object = SharedObject.create()
object.doSomething()
// The C++ constructor is imported as a Swift initializer
Copy link
Author

Choose a reason for hiding this comment

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

Comment should be next the the line where we are calling the initializer

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.
Copy link
Author

@fahadnayyar fahadnayyar Jul 2, 2025

Choose a reason for hiding this comment

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

Create a new section here: Constructing Shared Reference

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: should be "Constructing Shared References" (plural "References")

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.
Copy link
Author

Choose a reason for hiding this comment

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

drop directly.

Rewrite it like this:
As illustrated in the above example, from Swift 6.2 onwards you can create instances of SWIFT_SHARED_REFERENCE types by calling its initializer.

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.

**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.
Copy link
Author

Choose a reason for hiding this comment

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

Note that the Swift compiler. default need not be in italics

In the event that you'd like to hide constructors you can also elete the default new operator in C++.

Copy link
Author

Choose a reason for hiding this comment

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

Remove the sentence If you'd like to prevent Swift from importing constructors as initializers, you can also delete the default new operator in C++.

Copy link
Contributor

@j-hui j-hui Jul 3, 2025

Choose a reason for hiding this comment

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

Oops I think we were looking at this at the same time. Here's my suggestion:

Suggested change
**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.
Note that Swift uses the default `new` operator for constructing C++ shared reference types.
To prevent Swift from importing constructors as initializers, delete the `new` operator in C++.

**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.


Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.
Copy link
Author

Choose a reason for hiding this comment

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

You can also import a user defined static factory function as a Swift initializer by annotating it with SWIFT_NAME("init(...)"), where the number of _ placeholders matches the number of parameters in the factory function. For example ... (no need to have a new paragraph).

Copy link
Contributor

Choose a reason for hiding this comment

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

Another suggestion: replace ... with to make it clear the ellipsis should be understood as a meta-variable and not taken verbatim.

I don't think "user-defined" is necessary here.

Suggested change
Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.
You can also import a static factory function as a Swift initializer by annotating it with `SWIFT_NAME("init()")`, where the `init(…)` Swift signature has the same number of parameters as the C++ factory function.
For example:

object.doSomething()
```

**Note**: If a C++ constructor and a user-annotated static factory (via `SWIFT_NAME`) have identical parameter signatures, Swift prefers the static factory when resolving initializer calls. Using `SWIFT_NAME("init(...)")` is especially useful if you want to use a custom allocator or you want to disable direct construction entirely and expose only factories.
Copy link
Author

Choose a reason for hiding this comment

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

Make this also as : Note that.

Copy link
Author

Choose a reason for hiding this comment

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

Remove the note completely


Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.

For example, consider a factory that performs custom allocation or returns a singleton instance:
Copy link
Author

Choose a reason for hiding this comment

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

Make it only For Example,

Copy link
Contributor

@j-hui j-hui Jul 3, 2025

Choose a reason for hiding this comment

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

Suggested change
For example, consider a factory that performs custom allocation or returns a singleton instance:

(deleted here so that "For example" can be elided into the previous paragraph; see above)


```cpp
struct SharedObject {
static SharedObject* make(int id) SWIFT_NAME("init(_:)");
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: indentation

Suggested change
static SharedObject* make(int id) SWIFT_NAME("init(_:)");
static SharedObject* make(int id) SWIFT_NAME("init(_:)");

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.

**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.
Copy link
Contributor

@j-hui j-hui Jul 3, 2025

Choose a reason for hiding this comment

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

Oops I think we were looking at this at the same time. Here's my suggestion:

Suggested change
**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.
Note that Swift uses the default `new` operator for constructing C++ shared reference types.
To prevent Swift from importing constructors as initializers, delete the `new` operator in C++.

// `object` will be released here.
```

You can create instances of `SharedObject` directly from Swift by calling its C++ constructor through a Swift initializer.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: should be "Constructing Shared References" (plural "References")


Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.

For example, consider a factory that performs custom allocation or returns a singleton instance:
Copy link
Contributor

@j-hui j-hui Jul 3, 2025

Choose a reason for hiding this comment

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

Suggested change
For example, consider a factory that performs custom allocation or returns a singleton instance:

(deleted here so that "For example" can be elided into the previous paragraph; see above)

**NOTE:** Swift uses *default* `new` operator for constructing c++ shared reference types. If you'd like to prevent Swift from importing constructors as initializers, you can also delete the *default* `new` operator in C++.


Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.
Copy link
Contributor

Choose a reason for hiding this comment

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

Another suggestion: replace ... with to make it clear the ellipsis should be understood as a meta-variable and not taken verbatim.

I don't think "user-defined" is necessary here.

Suggested change
Alternatively, you can also construct instances of `SharedObject` using a user-defined static factory function, provided that the factory function is annotated with `SWIFT_NAME("init(...)")`, where the number of `_` placeholders matches the number of parameters in the factory function.
You can also import a static factory function as a Swift initializer by annotating it with `SWIFT_NAME("init()")`, where the `init(…)` Swift signature has the same number of parameters as the C++ factory function.
For example:

In this case, Swift will import the static `make` function as a Swift initializer:

```swift
let object = SharedObject(id: 42)
Copy link
Contributor

Choose a reason for hiding this comment

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

The id label shouldn't be there, i.e.,

Suggested change
let object = SharedObject(id: 42)
let object = SharedObject(42)

But I think you should give more examples here. Also, doSomething() isn't really necessary here.

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.

3 participants