Desired Swift language features that can advance the state of C++ interoperability support

Swift 5.9 can import and use a wide array of C++ types in Swift. However, not all types categories are supported. This post lists the set of desired Swift language features that would allow us to support most C++ types in Swift:

  • Generics support for non-copyable types. While Swift 5.9 added support for non-copyable structs and enums, these types still are not allowed to be used as a generic type argument. This is a key issue that prevents us from fully completing support for move-only C++ types in Swift, as we need to form types like UnsafePointer<MoveOnlyCxxType> without language restrictions.
  • Adding to the point above, types like UnsafePointer and UnsafeMutablePointer should provide support for borrowing and mutably borrowing the non-copyable pointee.
  • Non-movable/non-escapable Swift type category. A non-escapable and non-copyable Swift type would allow us to import and model non-copyable and non-movable C++ types in Swift.

Additionally, the following language features would help improve ergonomics for some of the common operations performed on C++ types in Swift:

  • Ability to perform a borrowing for loop over a Swift Sequence, that does need to go through a IteratorProtocol but rather can use indexed iteration instead. This would let us use for loop on non-random access collections like std::map automatically.

I would like to bring the items listed above to the attention of the @language-workgroup to make sure that their plans and ideas for evolution of Swift can factor in these requests into account as well.

11 Likes

Thanks Alex. These sound in line with projects we plan to round out noncopyable types support in general, which is nice. Would it also make sense to include internal import on this list, as well as support for importing C and C++ types without transitively exposing their ABI, in order to allow packages to use C++ interop internally without requiring dependents to know about it?

6 Likes

Yeah, great point, I forgot to include these items as well.

I have on occasion used C++'s ability to use integer values rather than types as template parameters, as in template<int x>. Just recently I found myself wishing I could do that in Swift. I imagine that would be a significant undertaking to add to Swift generics.

2 Likes

Rust calls these const generics I believe, and they took a long time to get them into even the unstable version of the language. I’m not aware of the effort it would require to bring these to Swift.

1 Like

Can we have a discussion on how we’d like to pursue inheritance and polymorphism? I am very eager to learn more about this and help move it forward.

1 Like

We have had some adopter requests for supporting non-type template parameters. So perhaps the language workgroup could consider whether Swift could support some non-type generic parameters as well.

Additionally, we had some requests related to supporting complicated templates where the user wants to choose whether to specify a default template parameter or not. So perhaps Swift could consider supporting default values in generic parameters as well.

I think default values would be more interesting as in principle you could model a useful subset of non-type template parameters as types and bring that into Swift in a different manner, so there's some limited workaround for non-type template parameters, but not really for default values. I suppose perhaps variadic generics could help here, as you could instantiate different template based on the the number of generic parameters :thinking:

2 Likes

For sure, I can start a new thread about that.

Another thing that would be good to have are borrow/inout bindings. Additionally, if we can have if borrow x = that's equivalent to if let that would be cool. We could then have a more workable and null-safe ability to work with shared_ptr , for instance we could then mutate the pointee using something like this:

let ptr = std.make_shared(std.string.Type)
if inout x = ptr.pointee  {
  x.append("mutation")
}

where pointee would have _read and _modify accessors that yield nil or element_type.

3 Likes

We hoped for that for years when we worked on the SwiftFusion project (before S4TF went away). Turned out to be harder than we thought, and we decided to use gyb to generate source files. Not ideal but kinda works. CC @David_Catmull