Files
carbon-lang/docs/design/README.md
T
Jon Meow d031f3cdab An incomplete, early, and in-progress overview of the language design. (#83)
Co-authored by: chandlerc

- Based on [PR 22](https://github.com/carbon-language/carbon-lang/pull/83)
- [Idea topic](https://forums.carbon-lang.dev/t/proposal-for-an-incomplete-rough-high-level-overview-ready-for-early-feedback/52)
- [RFC](https://forums.carbon-lang.dev/t/rfc-an-incomplete-early-and-in-progress-overview-of-the-language-design/73)
- [Decision announcement](https://forums.carbon-lang.dev/t/accepted-an-incomplete-early-and-in-progress-overview-of-the-language-design/110)

This proposal should be considered a starting point of the language design. It's not intended to be final; language details may change. This is intended to offer a reasonable starting point for:

- Example code.
- Conceptualizing Carbon at a high level.
- Reasonable, but not necessarily final, approaches to features in README.md.
  - If any idea is obviously bad, we can clean it up here.

This proposal is not intended to achieve:

- A whole language design.
  - This is way too much work for a single proposal; this is a skeletal framework only.
  - As we work on feature-specific designs, we may decide to use other approaches. That's fine: we only need somewhere to start.
  - The summaries in README.md may be expected to change over time.
- Feature-specific files aren't intended to be well-written or comprehensive. They are a quick jot of prior thoughts.
  - We want to avoid getting stuck on language details that we should consider
    more carefully regardless. If you're passionate about a feature, please feel
    free to start a new proposal for it.
  - Each and every aspect of the suggested overview should be subject to careful
    examination and justification before it becomes a settled plan of record.

Chandler started this with https://github.com/carbon-language/carbon-lang/pull/22. I've taken it over with the following changes:

- More of a directory hierarchy.
- Trying to thin out the main file (now README.md) to lighter summaries of features.
- Details/rationale/alternatives should be in feature-specific files.
  - Draft files are linked as references where added.

For an example of how we may proceed with feature-specific designs, see https://github.com/carbon-language/carbon-lang/pull/80. In this structure:

- docs/design/README.md mentions interoperability, with a light overview.
  - The light overview is not yet in https://github.com/carbon-language/carbon-lang/pull/80.
- docs/design/interoperability/README.md goes into more depth on interoperability, covering key points of the approach.
- Individual files in docs/design/interoperability/* go into more depth on interoperability.

Simple designs may not have a subdirectory. All current feature-specific designs do not -- they may be moved later.
2020-07-30 11:37:15 -07:00

897 lines
28 KiB
Markdown

# Language design overview
<!--
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->
## Table of contents
<!-- toc -->
- [Context and disclaimer](#context-and-disclaimer)
- [Example code](#example-code)
- [Basic syntax](#basic-syntax)
- [Code and comments](#code-and-comments)
- [Files, libraries, and packages](#files-libraries-and-packages)
- [Names and scopes](#names-and-scopes)
- [Naming conventions](#naming-conventions)
- [Aliases](#aliases)
- [Name lookup](#name-lookup)
- [Name lookup for common types](#name-lookup-for-common-types)
- [Expressions](#expressions)
- [Functions](#functions)
- [Blocks and statements](#blocks-and-statements)
- [Variables](#variables)
- [Lifetime and move semantics](#lifetime-and-move-semantics)
- [Control flow](#control-flow)
- [`if`/`else`](#ifelse)
- [`while`, `break`, and `continue`](#while-break-and-continue)
- [`return`](#return)
- [Types](#types)
- [Primitive types](#primitive-types)
- [Composite types](#composite-types)
- [Tuples](#tuples)
- [Variants](#variants)
- [Pointers and references](#pointers-and-references)
- [Arrays and slices](#arrays-and-slices)
- [User-defined types](#user-defined-types)
- [Structs](#structs)
- [Allocation, construction, and destruction](#allocation-construction-and-destruction)
- [Assignment, copying, and moving](#assignment-copying-and-moving)
- [Comparison](#comparison)
- [Implicit and explicit conversion](#implicit-and-explicit-conversion)
- [Inline type composition](#inline-type-composition)
- [Unions](#unions)
- [Pattern matching](#pattern-matching)
- [`match` control flow](#match-control-flow)
- [Pattern matching in local variables](#pattern-matching-in-local-variables)
- [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)
- [Type abstractions](#type-abstractions)
- [Interfaces](#interfaces)
- [Generics](#generics)
- [Templates](#templates)
- [Types with template parameters](#types-with-template-parameters)
- [Functions with template parameters](#functions-with-template-parameters)
- [Overloading](#overloading)
- [Metaprogramming](#metaprogramming)
- [Execution abstractions](#execution-abstractions)
- [Abstract machine and execution model](#abstract-machine-and-execution-model)
- [Lambdas](#lambdas)
- [Co-routines](#co-routines)
- [Bidirectional interoperability with C/C++](#bidirectional-interoperability-with-cc)
<!-- tocstop -->
## Context and disclaimer
Eventually, this document hopes to provide a high-level overview of the design
of the Carbon language. It should summarize the key points across the different
aspects of the language design and link to more detailed and comprehensive
design documents to expand on specific aspects of the design. That means it
isn't and doesn't intend to be complete or stand on its own. Notably, it doesn't
attempt to provide detailed and comprehensive justification for design
decisions. Those should instead be provided by the dedicated and focused designs
linked to from here. However, it should provide an overarching view of the
design and a good basis for diving into specific details.
However, these are extremely early days for Carbon. Currently, this document
tries to capture two things:
1. Initial musings about what _might_ make sense as a basis for Carbon. These
are largely informed by idle discussions between C++ and Clang developers
over the years, and should not be given any particular weight.
2. A summary and snapshot of in-progress efforts to flesh out and motivate
specific designs for parts of the language.
The utility of capturing these at this early stage is primarily to give everyone
a reasonably consistent set of terminology and context as we begin fleshing out
concrete (and well justified) designs for each part of the language. In some
cases, it captures ideas that may be interesting to explore, but isn't meant to
overly anchor on them. Any ideas here need to be fully explored and justified
with a detailed analysis. The context of #1 (directly evolving C++, experience
building Clang, and experience working on C++ codebases including Clang and LLVM
themselves) is also important. It is both an important signal but also a bias.
### Example code
In order to keep example code consistent, we are making choices that may change
later. In particular, where `$` is shown in examples, it is a placeholder: `$`
is a well-known bad symbol due to international keyboard layouts, and will be
cleaned up during evolution.
## Basic syntax
### Code and comments
> References: [Lexical conventions](lexical_conventions.md)
>
> **TODO:** References need to be evolved.
- All source code is UTF-8 encoded text. For simplicity, no other encoding is
supported.
- Line comments look like `// ...`. However, they are required to be the only
non-whitespace on the line for readability.
- Block comments look like `//\{ ... //\}`, with each marker on its own line.
Nested block comments are supported using named regions. For example:
```carbon
live code
//\{
commented code
//\{ nested block
commented code in nested block
//\} nested block
//\}
live code
```
### Files, libraries, and packages
> References: [Files, libraries and packages](files_libraries_and_packages.md)
>
> **TODO:** References need to be evolved.
Carbon code is organized into files, libraries, and packages:
- A **file** is the unit of compilation.
- A **library** can be made up of multiple files, and is the unit whose public
interface can be imported.
- A **package** is a collection of one or more libraries, typically ones with
a single common source and with some close association.
A file belongs to precisely one library, and a library belongs to precisely one
package.
Files have a `.6c` extension. They must start with a declaration of their
package and library. They may import both other libraries from within their
package, as well as libraries from other packages. For example:
```carbon
// This is a file in the "Eucalyptus" library of the "Koala" package.
package Koala library Eucalyptus;
// Import the "Wombat" library from the "Widget" package.
import Widget library Wombat;
// Import the "Container" library from the "Koala" package.
import library Container;
```
### Names and scopes
> References: [Lexical conventions](lexical_conventions.md)
>
> **TODO:** References need to be evolved.
Various constructs introduce a named entity in Carbon. These can be functions,
types, variables, or other kinds of entities that we'll cover. A name in Carbon
is always formed out of an "identifier", or a sequence of letters, numbers, and
underscores which starts with a letter. As a regular expression, this would be
`/[a-zA-Z][a-zA-Z0-9_]*/`. Eventually we may add support for more unicode
characters as well.
#### Naming conventions
> References: [Naming conventions](naming_conventions.md)
>
> **TODO:** References need to be evolved.
Our current proposed naming convention are:
- `UpperCamelCase` for names of compile-time resolved constants, whether they
participate in the type system or not.
- `lower_snake_case` for keywords and names of run-time resolved values.
As a matter of style and consistency, we will follow these conventions where
possible and encourage convergence.
For example:
- An integer that is a compile-time constant sufficient to use in the
construction a compile-time array size, such as a template function
parameter, might be named `N`.
- A generic function parameter's value can't be used during type-checking, but
might still be named `N`, since it will be a constant available to the
compiler at code generation time.
- Functions and most types will be in `UpperCamelCase`.
- A type where only run-time type information queries are available would end
up as `lower_snake_case`.
- A keyword like `import` uses `lower_snake_case`.
#### Aliases
> References: [Aliases](aliases.md)
>
> **TODO:** References need to be evolved.
Carbon provides a facility to declare a new name as an alias for a value. This
is a fully general facility because everything is a value in Carbon, including
types.
For example:
```carbon
alias MyInt = Int;
```
This creates an alias called `MyInt` for whatever `Int` resolves to. Code
textually after this can refer to `MyInt`, and it will transparently refer to
`Int`.
#### Name lookup
> References: [Name lookup](name_lookup.md)
>
> **TODO:** References need to be evolved.
Names are always introduced into some scope which defines where they can be
referenced. Many of these scopes are themselves named. `namespace` is used to
introduce a dedicated named scope, and we traverse nested names in a uniform way
with `.`-separated names. Unqualified name lookup will always find a file-local
result, including aliases.
For example:
```carbon
package Koala library Eucalyptus;
namespace Leaf {
namespace Vein {
fn Count() -> Int;
}
}
```
`Count` may be referred to as:
- `Count` from within the `Vein` namespace.
- `Vein.Count` from within the `Leaf` namespace.
- `Leaf.Vein.Count` from within this file.
- `Koala.Leaf.Vein.Count` from any arbitrary location.
Note that libraries do **not** introduce a scope; they share the scope of their
package.
##### Name lookup for common types
> References: [Name lookup](name_lookup.md)
>
> **TODO:** References need to be evolved.
Common types that we expect to be used universally will be provided for every
file, including `Int` and `Bool`. These will likely be defined in a special
"prelude" package.
### Expressions
> References: [Lexical conventions](lexical_conventions.md) and
> [operators](operators.md)
>
> **TODO:** References need to be evolved.
Expressions describe some computed value. The simplest example would be a
literal number like `42`: an expression that computes the integer value 42.
Some common expressions in Carbon include:
- Literals: `42`, `3.1419`, `"Hello World!"`
- Operators:
- Increment and decrement: `++i`, `--j`
- These do not return any result.
- Unary negation: `-x`
- Arithmetic: `1 + 2`, `3 - 4`, `2 * 5`, `6 / 3`
- Bitwise: `2 & 3`, `2 | 4`, `3 ^ 1`, `~7`
- Bit shift: `1 << 3`, `8 >> 1`
- Comparison: `2 == 2`, `3 != 4`, `5 < 6`, `7 > 6`, `8 <= 8`, `8 >= 8`
- Logical: `a and b`, `c or d`
- Parenthesized expressions: `(7 + 8) * (3 - 1)`
### Functions
> References: [Functions](functions.md) and
> [syntactic conventions](syntactic_conventions.md)
>
> **TODO:** References need to be evolved.
Functions are the core unit of behavior. For example:
```carbon
fn Sum(Int: a, Int: b) -> Int;
```
Breaking this apart:
- `fn` is the keyword used to indicate a function.
- Its name is `Sum`.
- It accepts two `Int` parameters, `a` and `b`.
- It returns an `Int` result.
You would call this function like `Sum(1, 2)`.
### Blocks and statements
> References: [Blocks and statements](blocks_and_statements.md)
>
> **TODO:** References need to be evolved.
The body or definition of a function is provided by a block of code containing
statements. The body of a function is also a new, nested scope inside the
function's scope, meaning that parameter names are available.
Statements within a block are terminated by a semicolon. Each statement can,
among other things, be an expression.
For example, here is a function definition using a block of statements, one of
which is nested:
```carbon
fn Foo() {
Bar();
{
Baz();
}
}
```
### Variables
> References: [Variables](variables.md) and
> [syntactic conventions](syntactic_conventions.md)
>
> **TODO:** References need to be evolved.
Blocks introduce nested scopes and can contain local variable declarations that
work similarly to function parameters.
For example:
```carbon
fn Foo() {
var Int: x = 42;
}
```
Breaking this apart:
- `var` is the keyword used to indicate a variable.
- Its name is `x`.
- Its type is `Int`.
- It is initialized with the value `42`.
### Lifetime and move semantics
> References: TODO
>
> **TODO:** References need to be evolved.
### Control flow
> References: [Control flow](control_flow.md)
>
> **TODO:** References need to be evolved.
Blocks of statements are generally executed sequentially. However, statements
are the primary place where this flow of execution can be controlled.
#### `if`/`else`
> References: [Control flow](control_flow.md)
>
> **TODO:** References need to be evolved.
`if` and `else` are common flow control keywords, which can result in
conditional execution of statements.
For example:
```carbon
fn Foo(Int: x) {
if (x < 42) {
Bar();
} else if (x > 77) {
Baz();
}
}
```
Breaking the `Foo` function apart:
- `Bar()` is invoked if `x` is less than `42`.
- `Baz()` is invoked if `x` is greater than `77`.
- Nothing happens if `x` is between `42` and `77`.
#### `while`, `break`, and `continue`
> References: [Control flow](control_flow.md)
>
> **TODO:** References need to be evolved.
Loops will be supported with a low-level primitive `while` statement. `break`
will be a way to exit the `while` directly, while `continue` will skip the rest
of the current loop iteration.
For example:
```carbon
fn Foo() {
var Int: x = 0;
while (x < 42) {
if (ShouldStop()) break;
if (ShouldSkip(x)) {
++x;
continue;
}
Bar(x);
++x;
}
}
```
Breaking the `Foo` function apart:
- The while body is normally executed for all values of `x` in [0, 42).
- The increment of x at the end causes this.
- If `ShouldStop()` returns true, the `break` causes the `while` to exit
early.
- If `ShouldSkip()` returns true, the `continue` causes the `while` to restart
early.
- Otherwise, `Bar(x)` is called for values of `x` in [0, 42).
#### `return`
> References: [Control flow](control_flow.md)
>
> **TODO:** References need to be evolved.
The `return` statement ends the flow of execution within a function, returning
execution to the caller. If the function returns a value to the caller, that
value is provided by an expression in the return statement. This allows us to
complete the definition of our `Sum` function from earlier as:
```carbon
fn Sum(Int: a, Int: b) -> Int {
return a + b;
}
```
## Types
> References: [Primitive types](primitive_types.md), [tuples](tuples.md), and
> [structs](structs.md)
>
> **TODO:** References need to be evolved.
Carbon's core types are broken down into three categories:
- Primitive types
- Composite types
- User-defined types
The first two are intrinsic and directly built in the language. The last aspect
of types allows for defining new types.
Expressions compute values in Carbon, and these values are always strongly typed
much like in C++. However, an important difference from C++ is that types are
themselves modeled as values; specifically, compile-time constant values.
However, in simple cases this doesn't make much difference.
### Primitive types
> References: [Primitive types](primitive_types.md)
>
> **TODO:** References need to be evolved.
These types are fundamental to the language as they aren't either formed from or
modifying other types. They also have semantics that are defined from first
principles rather than in terms of other operations. These will be made
available through the [prelude package](#name-lookup-for-common-types).
Primitive types fall into the following categories:
- `Void` - a type with only one possible value: empty.
- `Bool` - a boolean type with two possible values: `True` and `False`.
- `Int` and `UInt` - signed and unsigned 64-bit integer types.
- Standard sizes are available, both signed and unsigned, including
`Int8`, `Int16`, `Int32`, `Int128`, and `Int256`.
- Overflow in either direction is an error.
- `Float64` - a floating point type with semantics based on IEEE-754.
- Standard sizes are available, including `Float16`, `Float32`, and
`Float128`.
- [`BFloat16`](primitive_types.md#bfloat16) is also provided.
- `String` - a byte sequence treated as containing UTF-8 encoded text.
- `StringView` - a read-only reference to a byte sequence treated as
containing UTF-8 encoded text.
### Composite types
#### Tuples
> References: [Tuples](tuples.md)
>
> **TODO:** References need to be evolved.
The primary composite type involves simple aggregation of other types as a
tuple. In formal type theory, tuples are product types.
An example use of tuples is:
```carbon
fn DoubleBoth(Int: x, Int: y) -> (Int, Int) {
return (2 * x, 2 * y);
}
```
Breaking this example apart:
- The return type is a tuple of two `Int` types.
- The expression uses tuple syntax to build a tuple of two `Int` values.
Both of these are expressions using the tuple syntax
`(<expression>, <expression>)`. The only difference is the type of the tuple
expression: one is a tuple of types, the other a tuple of values.
Element access uses subscript syntax:
```carbon
fn DoubleTuple((Int, Int): x) -> (Int, Int) {
return (2 * x[0], 2 * x[1]);
}
```
Tuples also support multiple indices and slicing to restructure tuple elements:
```carbon
// This reverses the tuple using multiple indices.
fn Reverse((Int, Int, Int): x) -> (Int, Int, Int) {
return x[2, 1, 0];
}
// This slices the tuple by extracting elements [0, 2).
fn RemoveLast((Int, Int, Int): x) -> (Int, Int) {
return x[0 .. 2];
}
```
#### Variants
> **TODO:** Needs a feature design and a high level summary provided inline.
#### Pointers and references
> **TODO:** Needs a feature design and a high level summary provided inline.
#### Arrays and slices
> **TODO:** Needs a feature design and a high level summary provided inline.
### User-defined types
#### Structs
> References: [Structs](structs.md)
>
> **TODO:** References need to be evolved.
`struct`s are a way for users to define their own data strutures or named
product types.
For example:
```carbon
struct Widget {
var Int: x;
var Int: y;
var Int: z;
var String: payload;
}
```
Breaking apart `Widget`:
- `Widget` has three `Int` members: `x`, `y`, and `z`.
- `Widget` has one `String` member: `payload`.
- Given an instance `dial`, a member can be referenced with `dial.paylod`.
More advanced `struct`s may be created:
```carbon
struct AdvancedWidget {
// Do a thing!
fn DoSomething(AdvancedWidget: self, Int: x, Int: y);
// A nested type.
struct Nestedtype {
// ...
}
private var Int: x;
private var Int: y;
}
fn Foo(AdvancedWidget: thing) {
thing.DoSomething(1, 2);
}
```
Breaking apart `AdvancedWidget`:
- `AdvancedWidget` has a public object method `DoSomething`.
- `DoSomething` explicitly indicates how the `AdvancedWidget` is passed to
it, and there is no automatic scoping - `self` must be specified as the
first input. The `self` name is also a keyword that explains how to
invoke this method on an object.
- `DoSomething` accepts `AdvancedWidget` _by value_, which is easily
expressed here along with other constraints on the object parameter.
- `AdvancedWidget` has two private data members: `x` and `y`.
- Private methods and data members are restricted to use by
`AdvancedWidget` only, providing a layer of easy validation of the most
basic interface constraints.
- `Nestedtype` is a nested type, and can be accessed as
`AdvancedWidget.Nestedtype`.
##### Allocation, construction, and destruction
> **TODO:** Needs a feature design and a high level summary provided inline.
##### Assignment, copying, and moving
> **TODO:** Needs a feature design and a high level summary provided inline.
##### Comparison
> **TODO:** Needs a feature design and a high level summary provided inline.
##### Implicit and explicit conversion
> **TODO:** Needs a feature design and a high level summary provided inline.
##### Inline type composition
> **TODO:** Needs a feature design and a high level summary provided inline.
#### Unions
> **TODO:** Needs a detailed design and a high level summary provided inline.
## Pattern matching
> References: [Pattern matching](pattern_matching.md)
>
> **TODO:** References need to be evolved.
The most prominent mechanism to manipulate and work with types in Carbon is
pattern matching. This may seem like a deviation from C++, but in fact this is
largely about building a clear, coherent model for a fundamental part of C++:
overload resolution.
### `match` control flow
> References: [Pattern matching](pattern_matching.md)
>
> **TODO:** References need to be evolved.
`match` is a control flow similar to `switch` of C/C++ and mirrors similar
constructs in other languages, such as Swift.
An example `match` is:
```carbon
fn Bar() -> (Int, (Float, Float));
fn Foo() -> Float {
match (Bar()...) {
case (42, (Float: x, Float: y)) => {
return x - y;
}
case (Int: p, (Float: x, Float: _)) if (p < 13) => {
return p * x;
}
case (Int: p, auto: _) if (p > 3) => {
return p * Pi;
}
default => {
return Pi;
}
}
}
```
Breaking apart this `match`:
- It accepts a value that will be inspected; in this case, the result of the
call to `Bar()`.
- It then will find the _first_ `case` that matches this value, and
execute that block.
- If none match, then it executes the default block.
- Each `case` pattern contains a value pattern, such as `(Int: p, auto: _)`,
followed by an optional boolean predicate introduced by the `if` keyword.
- The value pattern must first match, and then the predicate must also
evaluate to true for the overall `case` pattern to match.
- Using `auto` for a type will always match.
Value patterns may be composed of the following:
- An expression, such as `42`, whose value must be equal to match.
- An optional type, such as `Int`, followed by a `:` and an identifier to bind
the value.
- The special identifier `_` may be used to discard the value once
matched.
- A destructuring pattern containing a sequence of value patterns, such as
`(Float: x, Float: y)`, which match against tuples and tuple-like values by
recursively matching on their elements.
- An unwrapping pattern containing a nested value pattern which matches
against a variant or variant-like value by unwrapping it.
### Pattern matching in local variables
> References: [Pattern matching](pattern_matching.md)
>
> **TODO:** References need to be evolved.
Value patterns may be used when declaring local variables to conveniently
destructure them and do other type manipulations. However, the patterns must
match at compile time, so a boolean predicate cannot be used directly.
An example use is:
```carbon
fn Bar() -> (Int, (Float, Float));
fn Foo() -> Int {
var (Int: p, auto: _) = Bar();
return p;
}
```
To break this apart:
- The `Int` returned by `Bar()` matches and is bound to `p`, then returned.
- The `(Float, Float)` returned by `Bar()` matches and is discarded by
`auto: _`.
### Pattern matching as function overload resolution
> References: [Pattern matching](pattern_matching.md)
>
> **TODO:** References need to be evolved. Needs a detailed design and a high
> level summary provided inline.
## Type abstractions
### Interfaces
> **TODO:** Needs a feature design and a high level summary provided inline.
### Generics
> **TODO:** Needs a feature design and a high level summary provided inline.
### Templates
> References: [Templates](templates.md)
>
> **TODO:** References need to be evolved.
Carbon templates follow the same fundamental paradigm as C++ templates: they are
instantiated when called, resulting in late type checking, duck typing, and lazy
binding. Although generics are generally preferred, templates enable translation
of code between C++ and Carbon, and address some cases where the type checking
rigor of generics are problematic.
#### Types with template parameters
> References: [Templates](templates.md)
>
> **TODO:** References need to be evolved.
User-defined types may have template parameters. The resulting type-function may
be used to instantiate the parameterized definition with the provided arguments
in order to produce a complete type. For example:
```carbon
struct Stack(Type:$$ T) {
var Array(T): storage;
fn Push(T: value);
fn Pop() -> T;
}
```
Breaking apart the template use in `Stack`:
- `Stack` is a paremeterized type accepting a type `T`.
- `T` may be used within the definition of `Stack` anywhere a normal type
would be used, and will only be type checked on instantiation.
- `var Array(T)` instantiates a parameterized type `Array` when `Stack` is
instantiated.
#### Functions with template parameters
> References: [Templates](templates.md)
>
> **TODO:** References need to be evolved.
Both implicit and explicit function parameters in Carbon can be marked as
_template_ parameters. When called, the arguments to these parameters trigger
instantiation of the function definition, fully type checking and resolving that
definition after substituting in the provided (or computed if implicit)
arguments. The runtime call then passes the remaining arguments to the resulting
complete definition.
```carbon
fn Convert[Type:$$ T](T: source, Type:$$ U) -> U {
var U: converted = source;
return converted;
}
fn Foo(Int: i) -> Float {
// Instantiates with the `T` implicit argument set to `Int` and the `U`
// explicit argument set to `Float`, then calls with the runtime value `i`.
return Convert(i, Float);
}
```
Here we deduce one type parameter and explicitly pass another. It is not
possible to explicitly pass a deduced type parameter; instead the call site
should cast or convert the argument to control the deduction. In this particular
example, the explicit type is passed after a runtime parameter. While this makes
that type unavailable to the declaration of _that_ runtime parameter, it still
is a _template_ parameter and available to use as a type in the remaining parts
of the function declaration.
#### Overloading
> References: [Templates](templates.md)
>
> **TODO:** References need to be evolved.
An important feature of templates in C++ is the ability to customize how they
end up specialized for specific arguments. Because template parameters (whether
as type parameters or function parameters) are pattern matched, we expect to
leverage pattern matching techniques to provide "better match" definitions that
are selected analogously to specializations in C++ templates. When expressed
through pattern matching, this may enable things beyond just template parameter
specialization, but that is an area that we want to explore cautiously.
> **TODO:** lots more work to flesh this out needs to be done...
## Metaprogramming
> References: [Metaprogramming](metaprogramming.md)
>
> **TODO:** References need to be evolved. Needs a detailed design and a high
> level summary provided inline.
Carbon provides metaprogramming facilities that look similar to regular Carbon
code. These are structured, and do not offer arbitrary inclusion or
preprocessing of source text such as C/C++ does.
## Execution abstractions
Carbon provides some higher-order abstractions of program execution, as well as
the critical underpinnings of such abstractions.
### Abstract machine and execution model
> **TODO:** Needs a feature design and a high level summary provided inline.
### Lambdas
> **TODO:** Needs a feature design and a high level summary provided inline.
### Co-routines
> **TODO:** Needs a feature design and a high level summary provided inline.
## Bidirectional interoperability with C/C++
> References:
> [Bidirectional interoperability with C/C++](interoperability/README.md)
>
> **TODO:** References need to be evolved. Needs a detailed design and a high
> level summary provided inline.