Skip to content

Commit fbf353a

Browse files
josh11bchandlercgeoffromer
authored
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>
1 parent 9ea4057 commit fbf353a

File tree

1 file changed

+289
-8
lines changed

1 file changed

+289
-8
lines changed

docs/design/README.md

+289-8
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,16 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8484
- [Generic type equality and `observe` declarations](#generic-type-equality-and-observe-declarations)
8585
- [Operator overloading](#operator-overloading)
8686
- [Common type](#common-type)
87-
- [Bidirectional interoperability with C/C++](#bidirectional-interoperability-with-cc)
87+
- [Bidirectional interoperability with C and C++](#bidirectional-interoperability-with-c-and-c)
88+
- [Goals](#goals)
89+
- [Non-goals](#non-goals)
90+
- [Importing and `#include`](#importing-and-include)
91+
- [ABI and dynamic linking](#abi-and-dynamic-linking)
92+
- [Operator overloading](#operator-overloading-1)
93+
- [Templates](#templates)
94+
- [Standard types](#standard-types)
95+
- [Inheritance](#inheritance-1)
96+
- [Enums](#enums)
8897
- [Unfinished tales](#unfinished-tales)
8998
- [Safety](#safety)
9099
- [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)
@@ -453,6 +462,10 @@ type `Optional(T*)`.
453462
Pointers are the main Carbon mechanism for allowing a function to modify a
454463
variable of the caller.
455464

465+
**TODO:** Perhaps Carbon will have
466+
[stricter pointer provenance](https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html)
467+
or restrictions on casts between pointers and integers.
468+
456469
> References:
457470
>
458471
> - Question-for-leads issue
@@ -1071,7 +1084,7 @@ This is instead of
10711084
10721085
#### `match`
10731086

1074-
`match` is a control flow similar to `switch` of C/C++ and mirrors similar
1087+
`match` is a control flow similar to `switch` of C and C++ and mirrors similar
10751088
constructs in other languages, such as Swift. The `match` keyword is followed by
10761089
an expression in parentheses, whose value is matched against the `case`
10771090
declarations, each of which contains a [refutable pattern](#refutable-patterns),
@@ -1553,7 +1566,7 @@ This type can be used from another package:
15531566
```carbon
15541567
package ExampleUser;
15551568
1556-
import Geometry library("OneSide");
1569+
import Geometry library "OneSide";
15571570
15581571
fn Foo(Geometry.Shapes.Flat.Circle circle) { ... }
15591572
```
@@ -2179,6 +2192,8 @@ The interfaces that correspond to each operator are given by:
21792192
[`As(U)`](expressions/as_expressions.md#extensibility) interface
21802193
- Implicit conversions use
21812194
[`ImplicitAs(U)`](expressions/implicit_conversions.md#extensibility)
2195+
- **TODO:** [Assignment](#assignment-statements): `x = y`, `++x`, `x += y`,
2196+
and so on
21822197
- **TODO:** Dereference: `*p`
21832198
- **TODO:** Indexing: `a[3]`
21842199
- **TODO:** Function call: `f(4)`
@@ -2243,17 +2258,283 @@ The common type is required to be a type that both types have an
22432258
> - Question-for-leads issue
22442259
> [#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)
22452260
2246-
## Bidirectional interoperability with C/C++
2247-
2248-
> **TODO:** Needs a detailed design and a high level summary provided inline.
2261+
## Bidirectional interoperability with C and C++
2262+
2263+
Interoperability, or _interop_, is the ability to call C and C++ code from
2264+
Carbon code and the other way around. This ability achieves two goals:
2265+
2266+
- Allows sharing a code and library ecosystem with C and C++.
2267+
- Allows incremental migration to Carbon from C and C++.
2268+
2269+
Carbon's approach to interopp is most similar to
2270+
[Java/Kotlin interop](interoperability/philosophy_and_goals.md#other-interoperability-layers),
2271+
where the two languages are different, but share enough of runtime model that
2272+
data from one side can be used from the other. For example, C++ and Carbon will
2273+
use the same
2274+
[memory model](https://en.cppreference.com/w/cpp/language/memory_model).
2275+
2276+
The design for interoperability between Carbon and C++ hinges on:
2277+
2278+
1. The ability to interoperate with a wide variety of code, such as
2279+
classes/structs and
2280+
[templates](<https://en.wikipedia.org/wiki/Template_(C%2B%2B)>), not just
2281+
free functions.
2282+
2. A willingness to expose the idioms of C++ into Carbon code, and the other
2283+
way around, when necessary to maximize performance of the interoperability
2284+
layer.
2285+
3. The use of wrappers and generic programming, including templates, to
2286+
minimize or eliminate runtime overhead.
2287+
2288+
This feature will have some restrictions; only a subset of Carbon APIs will be
2289+
available to C++ and a subset of C++ APIs will be available to Carbon.
2290+
2291+
- To achieve simplification in Carbon, its programming model will exclude some
2292+
rarely used and complex features of C++. For example, there will be
2293+
limitations on
2294+
[multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance).
2295+
- C or C++ features that compromise the performance of code that don't use
2296+
that feature, like
2297+
[RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) and
2298+
[exceptions](https://en.wikipedia.org/wiki/Exception_handling), are in
2299+
particular subject to revision in Carbon.
22492300

22502301
> References:
22512302
>
22522303
> - [Bidirectional interoperability with C/C++](interoperability/README.md)
22532304
> - Proposal
22542305
> [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175)
2306+
2307+
### Goals
2308+
2309+
The [goals for interop](interoperability/philosophy_and_goals.md#goals) include:
2310+
2311+
- [Support mixing Carbon and C++ toolchains](interoperability/philosophy_and_goals.md#support-mixing-carbon-and-c-toolchains)
2312+
- [Compatibility with the C++ memory model](interoperability/philosophy_and_goals.md#compatibility-with-the-c-memory-model)
2313+
- [Minimize bridge code](interoperability/philosophy_and_goals.md#minimize-bridge-code)
2314+
- [Unsurprising mappings between C++ and Carbon types](interoperability/philosophy_and_goals.md#unsurprising-mappings-between-c-and-carbon-types)
2315+
- [Allow C++ bridge code in Carbon files](interoperability/philosophy_and_goals.md#allow-c-bridge-code-in-carbon-files)
2316+
- [Carbon inheritance from C++ types](interoperability/philosophy_and_goals.md#carbon-inheritance-from-c-types)
2317+
- [Support use of advanced C++ features](interoperability/philosophy_and_goals.md#support-use-of-advanced-c-features)
2318+
- [Support basic C interoperability](interoperability/philosophy_and_goals.md#support-basic-c-interoperability)
2319+
2320+
> References:
22552321
>
2256-
> **TODO:** References need to be evolved.
2322+
> - [Interoperability: Goals](interoperability/philosophy_and_goals.md#goals)
2323+
2324+
### Non-goals
2325+
2326+
The [non-goals for interop](interoperability/philosophy_and_goals.md#non-goals)
2327+
include:
2328+
2329+
- [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)
2330+
- [Never require bridge code](interoperability/philosophy_and_goals.md#never-require-bridge-code)
2331+
- [Convert all C++ types to Carbon types](interoperability/philosophy_and_goals.md#convert-all-c-types-to-carbon-types)
2332+
- [Support for C++ exceptions without bridge code](interoperability/philosophy_and_goals.md#support-for-c-exceptions-without-bridge-code)
2333+
- [Cross-language metaprogramming](interoperability/philosophy_and_goals.md#cross-language-metaprogramming)
2334+
- [Offer equivalent support for languages other than C++](interoperability/philosophy_and_goals.md#offer-equivalent-support-for-languages-other-than-c)
2335+
2336+
> References:
2337+
>
2338+
> - [Interoperability: Non-goals](interoperability/philosophy_and_goals.md#non-goals)
2339+
2340+
### Importing and `#include`
2341+
2342+
A C++ library header file may be [imported](#packages-libraries-namespaces) into
2343+
Carbon using an `import` declaration of the special `Cpp` package.
2344+
2345+
```carbon
2346+
// like `#include "circle.h"` in C++
2347+
import Cpp library "circle.h"
2348+
```
2349+
2350+
This adds the names from `circle.h` into the `Cpp` namespace. If `circle.h`
2351+
defines some names in a `namespace shapes { ... }` scope, those will be found in
2352+
Carbon's `Cpp.shapes` namespace.
2353+
2354+
In the other direction, Carbon packages can export a header file to be
2355+
`#include`d from C++ files.
2356+
2357+
```c++
2358+
// like `import Geometry` in Carbon
2359+
#include "geometry.carbon.h"
2360+
```
2361+
2362+
Generally Carbon entities will be usable from C++ and C++ entities will be
2363+
usable from Carbon. This includes types, function, and constants. Some entities,
2364+
such as Carbon interfaces, won't be able to be translated directly.
2365+
2366+
C and C++ macros that are defining constants will be imported as constants.
2367+
Otherwise, C and C++ macros will be unavailable in Carbon. C and C++ `typedef`s
2368+
would be translated into type constants, as if declared using a
2369+
[`let`](#constant-let-declarations).
2370+
2371+
Carbon functions and types that satisfy some restrictions may be annotated as
2372+
exported to C as well, like C++'s
2373+
[`extern "C"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)
2374+
marker.
2375+
2376+
### ABI and dynamic linking
2377+
2378+
Carbon itself will not have a stable ABI for the language as a whole, and most
2379+
language features will be designed around not having any ABI stability. Instead,
2380+
we expect to add dedicated language features that are specifically designed to
2381+
provide an ABI-stable boundary between two separate parts of a Carbon program.
2382+
These ABI-resilient language features and API boundaries will be opt-in and
2383+
explicit. They may also have functionality restrictions to make them easy to
2384+
implement with strong ABI resilience.
2385+
2386+
When interoperating with already compiled C++ object code or shared libraries,
2387+
the C++ interop may be significantly less feature rich than otherwise. This is
2388+
an open area for us to explore, but we expect to require re-compiling C++ code
2389+
in order to get the full ergonomic and performance benefits when interoperating
2390+
with Carbon. For example, recompilation lets us ensure Carbon and C++ can use
2391+
the same representation for key vocabulary types.
2392+
2393+
However, we expect to have full support for the C ABI when interoperating with
2394+
already-compiled C object code or shared libraries. We expect Carbon's bridge
2395+
code functionality to cover similar use cases as C++'s
2396+
[`extern "C"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)
2397+
marker in order to provide full bi-directional support here. The functionality
2398+
available across this interop boundary will of course be restricted to what is
2399+
expressible in the C ABI, and types may need explicit markers to have guaranteed
2400+
ABI compatibility.
2401+
2402+
### Operator overloading
2403+
2404+
[Operator overloading](#operator-overloading) is supported in Carbon, but is
2405+
done by [implementing an interface](#interfaces-and-implementations) instead of
2406+
defining a method or nonmember function as in C++.
2407+
2408+
Carbon types implementing an operator overload using an interface should get the
2409+
corresponding operator overload in C++. So implementing `ModWith(U)` in Carbon
2410+
for a type effectively implements `operator%` in C++ for that type. This also
2411+
works in the other direction, so C++ types implementing an operator overload are
2412+
automatically considered to implement the corresponding Carbon interface. So
2413+
implementing `operator%` in C++ for a type also implements interface
2414+
`ModWith(U)` in Carbon. However, there may be edge cases around implicit
2415+
conversions or overload selection that don't map completely into Carbon.
2416+
2417+
In some cases, the operation might be written differently in the two languages.
2418+
In those cases, they are matched according to which operation has the most
2419+
similar semantics rather than using the same symbols. For example, the `^x`
2420+
operation and `BitComplement` interface in Carbon corresponds to the `~x`
2421+
operation and `operator~` function in C++. Similarly, the `ImplicitAs(U)` Carbon
2422+
interface corresponds to implicit conversions in C++, which can be written in
2423+
multiple different ways. Other
2424+
[C++ customization points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html)
2425+
like `swap` will correspond to a Carbon interface, on a case-by-case basis.
2426+
2427+
Some operators will only exist or be overridable in C++, such as logical
2428+
operators or the comma operator. In the unlikely situation where those operators
2429+
need to be overridden for a Carbon type, that can be done with a nonmember C++
2430+
function.
2431+
2432+
Carbon intefaces with no C++ equivalent, such as
2433+
[`CommonTypeWith(U)`](#common-type), may be implemented for C++ types externally
2434+
in Carbon code. To satisfy the orphan rule
2435+
([1](generics/details.md#impl-lookup), [2](generics/details.md#orphan-rule)),
2436+
each C++ library will have a corresponding Carbon wrapper library that must be
2437+
imported instead of the C++ library if the Carbon wrapper exists. **TODO:**
2438+
Perhaps it will automatically be imported, so a wrapper may be added without
2439+
requiring changes to importers?
2440+
2441+
### Templates
2442+
2443+
Carbon supports both
2444+
[checked and template generics](#checked-and-template-parameters). This provides
2445+
a migration path for C++ template code:
2446+
2447+
- C++ template -> Carbon template: This involves migrating the code from C++
2448+
to Carbon. If that migration is faithful, the change should be transparent
2449+
to callers.
2450+
- -> Carbon template with constraints: Constraints may be added one at a time.
2451+
Adding a constraint never changes the meaning of the code as long as it
2452+
continues to compile. Compile errors will point to types for which an
2453+
implementation of missing interfaces is needed. A temporary template
2454+
implementation of that interface can act as a bridge during the transition.
2455+
- -> Carbon checked generic: Once all callers work after all constraints have
2456+
been added, the template parameter may be switched to a checked generic.
2457+
2458+
Carbon will also provide direct interop with C++ templates in many ways:
2459+
2460+
- Ability to call C++ templates and use C++ templated types from Carbon.
2461+
- Ability to instantiate a C++ template with a Carbon type.
2462+
- Ability to instantiate a Carbon generic with a C++ type.
2463+
2464+
We expect the best interop in these areas to be based on a Carbon-provided C++
2465+
toolchain. However, even when using Carbon's generated C++ headers for interop,
2466+
we will include the ability where possible to use a Carbon generic from C++ as
2467+
if it were a C++ template.
2468+
2469+
### Standard types
2470+
2471+
The Carbon integer types, like `i32` and `u64`, are considered equal to the
2472+
corresponding fixed-width integer types in C++, like `int32_t` and `uint64_t`,
2473+
provided by `<stdint.h>` or `<cstdint>`. The basic C and C++ integer types like
2474+
`int`, `char`, and `unsigned long` are available in Carbon inside the `Cpp`
2475+
namespace given an `import Cpp;` declaration, with names like `Cpp.int`,
2476+
`Cpp.char`, and `Cpp.unsigned_long`. C++ types are considered different if C++
2477+
considers them different, so C++ overloads are resolved the same way. Carbon
2478+
[conventions for implicit conversions between integer types](expressions/implicit_conversions.md#data-types)
2479+
apply here, allowing them whenever the numerical value for all inputs may be
2480+
preserved by the conversion.
2481+
2482+
Other C and C++ types are equal to Carbon types as follows:
2483+
2484+
| C or C++ | Carbon |
2485+
| -------- | -------------- |
2486+
| `bool` | `bool` |
2487+
| `float` | `f32` |
2488+
| `double` | `f64` |
2489+
| `T*` | `Optional(T*)` |
2490+
| `T[4]` | `[T; 4]` |
2491+
2492+
Further, C++ reference types like `T&` will be translated to `T*` in Carbon,
2493+
which is Carbon's non-null pointer type.
2494+
2495+
Carbon will work to have idiomatic vocabulary _view_ types for common data
2496+
structures, like `std::string_view` and `std::span`, map transparently between
2497+
C++ and the Carbon equivalents. This will include data layout so that even
2498+
pointers to these types translate seamlessly, contingent on a suitable C++ ABI
2499+
for those types, potentially by re-compiling the C++ code with a customized ABI.
2500+
We will also explore how to expand coverage to similar view types in other
2501+
libraries.
2502+
2503+
However, Carbon's containers will be distinct from the C++ standard library
2504+
containers in order to maximize our ability to improve performance and leverage
2505+
language features like checked generics in their design and implementation.
2506+
2507+
Where possible, we will also try to provide implementations of Carbon's standard
2508+
library container _interfaces_ for the relevant C++ container types so that they
2509+
can be directly used with generic Carbon code. This should allow generic code in
2510+
Carbon to work seamlessly with both Carbon and C++ containers without
2511+
performance loss or constraining the Carbon container implementations. In the
2512+
other direction, Carbon containers will satisfy C++ container requirements, so
2513+
templated C++ code can operate directly on Carbon containers as well.
2514+
2515+
### Inheritance
2516+
2517+
[Carbon has single inheritance](#inheritance) allowing C++ classes using
2518+
inheritance to be migrated. The data representation will be consistent so that
2519+
Carbon classes may inherit from C++ classes, and the other way around, even with
2520+
virtual methods.
2521+
2522+
C++ [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance)
2523+
and [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
2524+
will be migrated using a combination of Carbon features. Carbon mixins support
2525+
implementation reuse and Carbon interfaces allow a type to implement multiple
2526+
APIs. However, there may be limits on the degree of interop available with
2527+
multiple inheritance across the C++ <-> Carbon boundaries.
2528+
2529+
Carbon dyn-safe interfaces may be exported to C++ as an
2530+
[abstract base class](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Abstract_and_concrete>).
2531+
The reverse operation is also possible using a proxy object implementing a C++
2532+
abstract base class and holding a pointer to a type implementing the
2533+
corresponding interface.
2534+
2535+
### Enums
2536+
2537+
> **TODO**
22572538
22582539
## Unfinished tales
22592540

@@ -2342,7 +2623,7 @@ This leads to Carbon's incremental path to safety:
23422623
23432624
Carbon provides metaprogramming facilities that look similar to regular Carbon
23442625
code. These are structured, and do not offer arbitrary inclusion or
2345-
preprocessing of source text such as C/C++ does.
2626+
preprocessing of source text such as C and C++ do.
23462627

23472628
> References: [Metaprogramming](metaprogramming.md)
23482629

0 commit comments

Comments
 (0)