Просмотр исходного кода

Design overview update part 4: C and C++ Interop (#1336)

This follows #1274 , #1325 , and #1328 . It fills in the "Bidirectional interoperability with C and C++" section.

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Co-authored-by: Geoff Romer <gromer@google.com>
josh11b 3 лет назад
Родитель
Сommit
fbf353afe8
1 измененных файлов с 289 добавлено и 8 удалено
  1. 289 8
      docs/design/README.md

+ 289 - 8
docs/design/README.md

@@ -84,7 +84,16 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [Generic type equality and `observe` declarations](#generic-type-equality-and-observe-declarations)
     -   [Generic type equality and `observe` declarations](#generic-type-equality-and-observe-declarations)
     -   [Operator overloading](#operator-overloading)
     -   [Operator overloading](#operator-overloading)
         -   [Common type](#common-type)
         -   [Common type](#common-type)
--   [Bidirectional interoperability with C/C++](#bidirectional-interoperability-with-cc)
+-   [Bidirectional interoperability with C and C++](#bidirectional-interoperability-with-c-and-c)
+    -   [Goals](#goals)
+    -   [Non-goals](#non-goals)
+    -   [Importing and `#include`](#importing-and-include)
+    -   [ABI and dynamic linking](#abi-and-dynamic-linking)
+    -   [Operator overloading](#operator-overloading-1)
+    -   [Templates](#templates)
+    -   [Standard types](#standard-types)
+    -   [Inheritance](#inheritance-1)
+    -   [Enums](#enums)
 -   [Unfinished tales](#unfinished-tales)
 -   [Unfinished tales](#unfinished-tales)
     -   [Safety](#safety)
     -   [Safety](#safety)
     -   [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)
     -   [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)
@@ -453,6 +462,10 @@ type `Optional(T*)`.
 Pointers are the main Carbon mechanism for allowing a function to modify a
 Pointers are the main Carbon mechanism for allowing a function to modify a
 variable of the caller.
 variable of the caller.
 
 
+**TODO:** Perhaps Carbon will have
+[stricter pointer provenance](https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html)
+or restrictions on casts between pointers and integers.
+
 > References:
 > References:
 >
 >
 > -   Question-for-leads issue
 > -   Question-for-leads issue
@@ -1071,7 +1084,7 @@ This is instead of
 
 
 #### `match`
 #### `match`
 
 
-`match` is a control flow similar to `switch` of C/C++ and mirrors similar
+`match` is a control flow similar to `switch` of C and C++ and mirrors similar
 constructs in other languages, such as Swift. The `match` keyword is followed by
 constructs in other languages, such as Swift. The `match` keyword is followed by
 an expression in parentheses, whose value is matched against the `case`
 an expression in parentheses, whose value is matched against the `case`
 declarations, each of which contains a [refutable pattern](#refutable-patterns),
 declarations, each of which contains a [refutable pattern](#refutable-patterns),
@@ -1553,7 +1566,7 @@ This type can be used from another package:
 ```carbon
 ```carbon
 package ExampleUser;
 package ExampleUser;
 
 
-import Geometry library("OneSide");
+import Geometry library "OneSide";
 
 
 fn Foo(Geometry.Shapes.Flat.Circle circle) { ... }
 fn Foo(Geometry.Shapes.Flat.Circle circle) { ... }
 ```
 ```
@@ -2179,6 +2192,8 @@ The interfaces that correspond to each operator are given by:
         [`As(U)`](expressions/as_expressions.md#extensibility) interface
         [`As(U)`](expressions/as_expressions.md#extensibility) interface
     -   Implicit conversions use
     -   Implicit conversions use
         [`ImplicitAs(U)`](expressions/implicit_conversions.md#extensibility)
         [`ImplicitAs(U)`](expressions/implicit_conversions.md#extensibility)
+-   **TODO:** [Assignment](#assignment-statements): `x = y`, `++x`, `x += y`,
+    and so on
 -   **TODO:** Dereference: `*p`
 -   **TODO:** Dereference: `*p`
 -   **TODO:** Indexing: `a[3]`
 -   **TODO:** Indexing: `a[3]`
 -   **TODO:** Function call: `f(4)`
 -   **TODO:** Function call: `f(4)`
@@ -2243,17 +2258,283 @@ The common type is required to be a type that both types have an
 > -   Question-for-leads issue
 > -   Question-for-leads issue
 >     [#1077: find a way to permit impls of CommonTypeWith where the LHS and RHS type overlap](https://github.com/carbon-language/carbon-lang/issues/1077)
 >     [#1077: find a way to permit impls of CommonTypeWith where the LHS and RHS type overlap](https://github.com/carbon-language/carbon-lang/issues/1077)
 
 
-## Bidirectional interoperability with C/C++
-
-> **TODO:** Needs a detailed design and a high level summary provided inline.
+## Bidirectional interoperability with C and C++
+
+Interoperability, or _interop_, is the ability to call C and C++ code from
+Carbon code and the other way around. This ability achieves two goals:
+
+-   Allows sharing a code and library ecosystem with C and C++.
+-   Allows incremental migration to Carbon from C and C++.
+
+Carbon's approach to interopp is most similar to
+[Java/Kotlin interop](interoperability/philosophy_and_goals.md#other-interoperability-layers),
+where the two languages are different, but share enough of runtime model that
+data from one side can be used from the other. For example, C++ and Carbon will
+use the same
+[memory model](https://en.cppreference.com/w/cpp/language/memory_model).
+
+The design for interoperability between Carbon and C++ hinges on:
+
+1.  The ability to interoperate with a wide variety of code, such as
+    classes/structs and
+    [templates](<https://en.wikipedia.org/wiki/Template_(C%2B%2B)>), not just
+    free functions.
+2.  A willingness to expose the idioms of C++ into Carbon code, and the other
+    way around, when necessary to maximize performance of the interoperability
+    layer.
+3.  The use of wrappers and generic programming, including templates, to
+    minimize or eliminate runtime overhead.
+
+This feature will have some restrictions; only a subset of Carbon APIs will be
+available to C++ and a subset of C++ APIs will be available to Carbon.
+
+-   To achieve simplification in Carbon, its programming model will exclude some
+    rarely used and complex features of C++. For example, there will be
+    limitations on
+    [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance).
+-   C or C++ features that compromise the performance of code that don't use
+    that feature, like
+    [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) and
+    [exceptions](https://en.wikipedia.org/wiki/Exception_handling), are in
+    particular subject to revision in Carbon.
 
 
 > References:
 > References:
 >
 >
 > -   [Bidirectional interoperability with C/C++](interoperability/README.md)
 > -   [Bidirectional interoperability with C/C++](interoperability/README.md)
 > -   Proposal
 > -   Proposal
 >     [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175)
 >     [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175)
+
+### Goals
+
+The [goals for interop](interoperability/philosophy_and_goals.md#goals) include:
+
+-   [Support mixing Carbon and C++ toolchains](interoperability/philosophy_and_goals.md#support-mixing-carbon-and-c-toolchains)
+-   [Compatibility with the C++ memory model](interoperability/philosophy_and_goals.md#compatibility-with-the-c-memory-model)
+-   [Minimize bridge code](interoperability/philosophy_and_goals.md#minimize-bridge-code)
+-   [Unsurprising mappings between C++ and Carbon types](interoperability/philosophy_and_goals.md#unsurprising-mappings-between-c-and-carbon-types)
+-   [Allow C++ bridge code in Carbon files](interoperability/philosophy_and_goals.md#allow-c-bridge-code-in-carbon-files)
+-   [Carbon inheritance from C++ types](interoperability/philosophy_and_goals.md#carbon-inheritance-from-c-types)
+-   [Support use of advanced C++ features](interoperability/philosophy_and_goals.md#support-use-of-advanced-c-features)
+-   [Support basic C interoperability](interoperability/philosophy_and_goals.md#support-basic-c-interoperability)
+
+> References:
 >
 >
-> **TODO:** References need to be evolved.
+> -   [Interoperability: Goals](interoperability/philosophy_and_goals.md#goals)
+
+### Non-goals
+
+The [non-goals for interop](interoperability/philosophy_and_goals.md#non-goals)
+include:
+
+-   [Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains](interoperability/philosophy_and_goals.md#full-parity-between-a-carbon-only-toolchain-and-mixing-ccarbon-toolchains)
+-   [Never require bridge code](interoperability/philosophy_and_goals.md#never-require-bridge-code)
+-   [Convert all C++ types to Carbon types](interoperability/philosophy_and_goals.md#convert-all-c-types-to-carbon-types)
+-   [Support for C++ exceptions without bridge code](interoperability/philosophy_and_goals.md#support-for-c-exceptions-without-bridge-code)
+-   [Cross-language metaprogramming](interoperability/philosophy_and_goals.md#cross-language-metaprogramming)
+-   [Offer equivalent support for languages other than C++](interoperability/philosophy_and_goals.md#offer-equivalent-support-for-languages-other-than-c)
+
+> References:
+>
+> -   [Interoperability: Non-goals](interoperability/philosophy_and_goals.md#non-goals)
+
+### Importing and `#include`
+
+A C++ library header file may be [imported](#packages-libraries-namespaces) into
+Carbon using an `import` declaration of the special `Cpp` package.
+
+```carbon
+// like `#include "circle.h"` in C++
+import Cpp library "circle.h"
+```
+
+This adds the names from `circle.h` into the `Cpp` namespace. If `circle.h`
+defines some names in a `namespace shapes { ... }` scope, those will be found in
+Carbon's `Cpp.shapes` namespace.
+
+In the other direction, Carbon packages can export a header file to be
+`#include`d from C++ files.
+
+```c++
+// like `import Geometry` in Carbon
+#include "geometry.carbon.h"
+```
+
+Generally Carbon entities will be usable from C++ and C++ entities will be
+usable from Carbon. This includes types, function, and constants. Some entities,
+such as Carbon interfaces, won't be able to be translated directly.
+
+C and C++ macros that are defining constants will be imported as constants.
+Otherwise, C and C++ macros will be unavailable in Carbon. C and C++ `typedef`s
+would be translated into type constants, as if declared using a
+[`let`](#constant-let-declarations).
+
+Carbon functions and types that satisfy some restrictions may be annotated as
+exported to C as well, like C++'s
+[`extern "C"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)
+marker.
+
+### ABI and dynamic linking
+
+Carbon itself will not have a stable ABI for the language as a whole, and most
+language features will be designed around not having any ABI stability. Instead,
+we expect to add dedicated language features that are specifically designed to
+provide an ABI-stable boundary between two separate parts of a Carbon program.
+These ABI-resilient language features and API boundaries will be opt-in and
+explicit. They may also have functionality restrictions to make them easy to
+implement with strong ABI resilience.
+
+When interoperating with already compiled C++ object code or shared libraries,
+the C++ interop may be significantly less feature rich than otherwise. This is
+an open area for us to explore, but we expect to require re-compiling C++ code
+in order to get the full ergonomic and performance benefits when interoperating
+with Carbon. For example, recompilation lets us ensure Carbon and C++ can use
+the same representation for key vocabulary types.
+
+However, we expect to have full support for the C ABI when interoperating with
+already-compiled C object code or shared libraries. We expect Carbon's bridge
+code functionality to cover similar use cases as C++'s
+[`extern "C"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)
+marker in order to provide full bi-directional support here. The functionality
+available across this interop boundary will of course be restricted to what is
+expressible in the C ABI, and types may need explicit markers to have guaranteed
+ABI compatibility.
+
+### Operator overloading
+
+[Operator overloading](#operator-overloading) is supported in Carbon, but is
+done by [implementing an interface](#interfaces-and-implementations) instead of
+defining a method or nonmember function as in C++.
+
+Carbon types implementing an operator overload using an interface should get the
+corresponding operator overload in C++. So implementing `ModWith(U)` in Carbon
+for a type effectively implements `operator%` in C++ for that type. This also
+works in the other direction, so C++ types implementing an operator overload are
+automatically considered to implement the corresponding Carbon interface. So
+implementing `operator%` in C++ for a type also implements interface
+`ModWith(U)` in Carbon. However, there may be edge cases around implicit
+conversions or overload selection that don't map completely into Carbon.
+
+In some cases, the operation might be written differently in the two languages.
+In those cases, they are matched according to which operation has the most
+similar semantics rather than using the same symbols. For example, the `^x`
+operation and `BitComplement` interface in Carbon corresponds to the `~x`
+operation and `operator~` function in C++. Similarly, the `ImplicitAs(U)` Carbon
+interface corresponds to implicit conversions in C++, which can be written in
+multiple different ways. Other
+[C++ customization points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html)
+like `swap` will correspond to a Carbon interface, on a case-by-case basis.
+
+Some operators will only exist or be overridable in C++, such as logical
+operators or the comma operator. In the unlikely situation where those operators
+need to be overridden for a Carbon type, that can be done with a nonmember C++
+function.
+
+Carbon intefaces with no C++ equivalent, such as
+[`CommonTypeWith(U)`](#common-type), may be implemented for C++ types externally
+in Carbon code. To satisfy the orphan rule
+([1](generics/details.md#impl-lookup), [2](generics/details.md#orphan-rule)),
+each C++ library will have a corresponding Carbon wrapper library that must be
+imported instead of the C++ library if the Carbon wrapper exists. **TODO:**
+Perhaps it will automatically be imported, so a wrapper may be added without
+requiring changes to importers?
+
+### Templates
+
+Carbon supports both
+[checked and template generics](#checked-and-template-parameters). This provides
+a migration path for C++ template code:
+
+-   C++ template -> Carbon template: This involves migrating the code from C++
+    to Carbon. If that migration is faithful, the change should be transparent
+    to callers.
+-   -> Carbon template with constraints: Constraints may be added one at a time.
+    Adding a constraint never changes the meaning of the code as long as it
+    continues to compile. Compile errors will point to types for which an
+    implementation of missing interfaces is needed. A temporary template
+    implementation of that interface can act as a bridge during the transition.
+-   -> Carbon checked generic: Once all callers work after all constraints have
+    been added, the template parameter may be switched to a checked generic.
+
+Carbon will also provide direct interop with C++ templates in many ways:
+
+-   Ability to call C++ templates and use C++ templated types from Carbon.
+-   Ability to instantiate a C++ template with a Carbon type.
+-   Ability to instantiate a Carbon generic with a C++ type.
+
+We expect the best interop in these areas to be based on a Carbon-provided C++
+toolchain. However, even when using Carbon's generated C++ headers for interop,
+we will include the ability where possible to use a Carbon generic from C++ as
+if it were a C++ template.
+
+### Standard types
+
+The Carbon integer types, like `i32` and `u64`, are considered equal to the
+corresponding fixed-width integer types in C++, like `int32_t` and `uint64_t`,
+provided by `<stdint.h>` or `<cstdint>`. The basic C and C++ integer types like
+`int`, `char`, and `unsigned long` are available in Carbon inside the `Cpp`
+namespace given an `import Cpp;` declaration, with names like `Cpp.int`,
+`Cpp.char`, and `Cpp.unsigned_long`. C++ types are considered different if C++
+considers them different, so C++ overloads are resolved the same way. Carbon
+[conventions for implicit conversions between integer types](expressions/implicit_conversions.md#data-types)
+apply here, allowing them whenever the numerical value for all inputs may be
+preserved by the conversion.
+
+Other C and C++ types are equal to Carbon types as follows:
+
+| C or C++ | Carbon         |
+| -------- | -------------- |
+| `bool`   | `bool`         |
+| `float`  | `f32`          |
+| `double` | `f64`          |
+| `T*`     | `Optional(T*)` |
+| `T[4]`   | `[T; 4]`       |
+
+Further, C++ reference types like `T&` will be translated to `T*` in Carbon,
+which is Carbon's non-null pointer type.
+
+Carbon will work to have idiomatic vocabulary _view_ types for common data
+structures, like `std::string_view` and `std::span`, map transparently between
+C++ and the Carbon equivalents. This will include data layout so that even
+pointers to these types translate seamlessly, contingent on a suitable C++ ABI
+for those types, potentially by re-compiling the C++ code with a customized ABI.
+We will also explore how to expand coverage to similar view types in other
+libraries.
+
+However, Carbon's containers will be distinct from the C++ standard library
+containers in order to maximize our ability to improve performance and leverage
+language features like checked generics in their design and implementation.
+
+Where possible, we will also try to provide implementations of Carbon's standard
+library container _interfaces_ for the relevant C++ container types so that they
+can be directly used with generic Carbon code. This should allow generic code in
+Carbon to work seamlessly with both Carbon and C++ containers without
+performance loss or constraining the Carbon container implementations. In the
+other direction, Carbon containers will satisfy C++ container requirements, so
+templated C++ code can operate directly on Carbon containers as well.
+
+### Inheritance
+
+[Carbon has single inheritance](#inheritance) allowing C++ classes using
+inheritance to be migrated. The data representation will be consistent so that
+Carbon classes may inherit from C++ classes, and the other way around, even with
+virtual methods.
+
+C++ [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance)
+and [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
+will be migrated using a combination of Carbon features. Carbon mixins support
+implementation reuse and Carbon interfaces allow a type to implement multiple
+APIs. However, there may be limits on the degree of interop available with
+multiple inheritance across the C++ <-> Carbon boundaries.
+
+Carbon dyn-safe interfaces may be exported to C++ as an
+[abstract base class](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Abstract_and_concrete>).
+The reverse operation is also possible using a proxy object implementing a C++
+abstract base class and holding a pointer to a type implementing the
+corresponding interface.
+
+### Enums
+
+> **TODO**
 
 
 ## Unfinished tales
 ## Unfinished tales
 
 
@@ -2342,7 +2623,7 @@ This leads to Carbon's incremental path to safety:
 
 
 Carbon provides metaprogramming facilities that look similar to regular Carbon
 Carbon provides metaprogramming facilities that look similar to regular Carbon
 code. These are structured, and do not offer arbitrary inclusion or
 code. These are structured, and do not offer arbitrary inclusion or
-preprocessing of source text such as C/C++ does.
+preprocessing of source text such as C and C++ do.
 
 
 > References: [Metaprogramming](metaprogramming.md)
 > References: [Metaprogramming](metaprogramming.md)