Update design docs for proposal #6710: char redesign (#7281)

Note that #7266 has already updated the toolchain for `char`, but not
`Core.CharLiteral`.

Assisted-by: Gemini via Antigravity

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
josh11b
2026-06-01 19:34:35 +00:00
committed by GitHub
co-authored by Josh L Geoff Romer
parent 49e5e15138
commit d01e1d2d06
9 changed files with 175 additions and 11 deletions
+1 -1
View File
@@ -3609,7 +3609,7 @@ provided by `<stdint.h>` or `<cstdint>`. The basic C and C++ integer types like
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)
[conventions for implicit conversions between integer types](expressions/implicit_conversions.md#numeric-types)
apply here, allowing them whenever the numerical value for all inputs may be
preserved by the conversion.
+30 -2
View File
@@ -17,6 +17,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [Overflow and other error conditions](#overflow-and-other-error-conditions)
- [Floating-point types](#floating-point-types)
- [Strings](#strings)
- [Character types](#character-types)
- [Overflow Semantics](#overflow-semantics)
- [Extensibility](#extensibility)
- [Alternatives considered](#alternatives-considered)
- [References](#references)
@@ -104,8 +106,8 @@ converted as follows:
- If one type is `iN` and the other type is `uM`, and `M` < `N`, the `uM`
operand is converted to `iN`.
- If one type is `fN` and the other type is `iM` or `uM`, and there is an
[implicit conversion](implicit_conversions.md#data-types) from the integer
type to `fN`, then the integer operand is converted to `fN`.
[implicit conversion](implicit_conversions.md#numeric-types) from the
integer type to `fN`, then the integer operand is converted to `fN`.
More broadly, if one operand is of built-in type and the other operand can be
implicitly converted to that type, then it is, unless that behavior is
@@ -185,6 +187,30 @@ Because floating-point arithmetic follows IEEE 754 rules: overflow results in
`+` for concatenation. See
[#457](https://github.com/carbon-language/carbon-lang/issues/457).
### Character types
Character types (`char` and `Core.CharLiteral`) support arithmetic operations
aligned with the concept of "characters" rather than raw integers. Operations
with `Core.CharLiteral` and compile-time constants produce compile-time integer
or `Core.CharLiteral` results. Operations with a `char` or a runtime integer
argument produce `char` results.
- **Addition:** The sum of a character and an integer produces a character.
- **Subtraction:**
- The difference of two characters produces an `i32`. This is preferred
even for `char` to be consistent with the range needed to represent the
difference of two `Core.CharLiteral` values.
- A character minus an integer produces a character, much like adding a
character to a negative integer.
#### Overflow Semantics
Arithmetic operations on `char` and `Core.CharLiteral` use error overflow
semantics [similar to signed integers](#overflow-and-other-error-conditions).
For example, `(('a' as char) + 500)` is invalid code because it causes `char`
overflow. That's why conversions are to signed values (for example,
`char as i16`).
## Extensibility
Arithmetic operators can be provided for user-defined types by implementing the
@@ -289,3 +315,5 @@ to give the semantics described above.
[#1083: Arithmetic](https://github.com/carbon-language/carbon-lang/pull/1083)
- Proposal
[#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)
+3 -2
View File
@@ -128,8 +128,9 @@ var e: i32 as GetType();
### Data types
In addition to the [implicit conversions](implicit_conversions.md#data-types),
the following numeric conversions are supported by `as`:
In addition to the
[implicit conversions](implicit_conversions.md#numeric-types), the following
numeric conversions are supported by `as`:
- `iN`, `uN`, or `fN` -> `fM`, for any `N` and `M`. Values that cannot be
exactly represented are suitably rounded to one of the two nearest
@@ -112,7 +112,7 @@ if (m > 1 == n > 1) {
### Built-in comparisons and implicit conversions
Built-in comparisons are permitted in three cases:
Built-in comparisons are permitted in the following cases:
1. When both operands are of standard Carbon integer types (`Int(n)` or
`Unsigned(n)`).
@@ -120,6 +120,7 @@ Built-in comparisons are permitted in three cases:
3. When one operand is of floating-point type and the other is of integer type,
if all values of the integer type can be exactly represented in the
floating-point type.
4. When both operands are of type `char` or `Core.CharLiteral`.
In each case, the result is the mathematically-correct answer. This applies even
when comparing `Int(n)` with `Unsigned(m)`.
@@ -225,7 +226,7 @@ We permit the following comparisons involving constants:
- Any two constants can be compared, even if there is no type that can
represent both.
As described in [implicit conversions](implicit_conversions.md#data-types),
As described in [implicit conversions](implicit_conversions.md#numeric-types),
integer constants can be implicitly converted to any integer or floating-point
type that can represent their value, and floating-point constants can be
implicitly converted to any floating-point type that can represent their value.
@@ -526,3 +527,5 @@ in general. That decision is left to a future proposal.
[#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)
- Issue
[#710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710)
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)
@@ -16,7 +16,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [Semantics-preserving](#semantics-preserving)
- [Examples](#examples)
- [Built-in types](#built-in-types)
- [Data types](#data-types)
- [Numeric types](#numeric-types)
- [Character types](#character-types)
- [Same type](#same-type)
- [Pointer conversions](#pointer-conversions)
- [Facet types](#facet-types)
@@ -98,7 +99,7 @@ salient part of a `StringView`'s value.
## Built-in types
### Data types
### Numeric types
The following implicit numeric conversions are available:
@@ -156,6 +157,17 @@ var a: u32 = ^0;
var b: u32 = a & ^4;
```
### Character types
A character constant can be implicitly converted to any non-literal character
type in which that value can be exactly represented. For now the only
non-literal character type is `char`, which represents a single UTF-8 code unit
in a single byte, and so implicit conversion from `Core.CharLiteral` to `char`
is only valid for values in the range `0x00`..`0x7F`.
No other implicit conversions (such as converting `char` to/from integer types
or `Core.CharLiteral` to integers) are permitted.
### Same type
The following conversion is available for every type `T`:
@@ -244,3 +256,5 @@ types.
[#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820).
- Proposal
[#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866).
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)
+31
View File
@@ -23,6 +23,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [Usage](#usage)
- [Alternatives considered](#alternatives-considered-1)
- [String literals](#string-literals)
- [Character literals](#character-literals)
- [Character type literals](#character-type-literals)
- [References](#references)
<!-- tocstop -->
@@ -249,6 +251,31 @@ String literal syntax is covered in the
No design for string types has been through the proposal process yet.
## Character literals
Character literals are defined in the
[character literals lexical conventions](../lexical_conventions/character_literals.md).
In Carbon, character literals have the type `Core.CharLiteral`, which represents
a single Unicode code point. This type supports addition and subtraction, see
[arithmetic](arithmetic.md#character-types). For example, `'a' + 1` results in a
`Core.CharLiteral` with value `'b'`. Operations that result in invalid Unicode
code points (such as `'a' + 0xFFFFFF`) are compile-time errors.
A `Core.CharLiteral` will implicitly convert to `char` if its value is in the
range `0x00`..`0x7F`, see
[implicit conversions](implicit_conversions.md#character-types).
## Character type literals
Carbon defines `char` as a type literal, which is the same type as `Core.Char`,
an adapter for `u8`.
- `char` notionally represents a single UTF-8 code unit.
- It can contain invalid UTF-8 code units, as long as it remains 8 bits. No
runtime validation is guaranteed.
- Carbon's string types use `char` for elements.
## References
- Proposal
@@ -259,7 +286,11 @@ No design for string types has been through the proposal process yet.
[#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543)
- Proposal
[#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866)
- Proposal
[#1964: Character Literals](https://github.com/carbon-language/carbon-lang/pull/1964)
- Proposal
[#2015: Numeric type literal syntax](https://github.com/carbon-language/carbon-lang/pull/2015)
- Question-for-leads issue
[#2113: Structure, scope, and naming of the prelude and syntax aliases](https://github.com/carbon-language/carbon-lang/issues/2113)
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)
+20 -2
View File
@@ -28,7 +28,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [TODO: Struct literals](#todo-struct-literals)
- [TODO: Accessing C++ classes, structs, and members](#todo-accessing-c-classes-structs-and-members)
- [TODO: Accessing global variables](#todo-accessing-global-variables)
- [TODO: Bi-directional type mapping: primitives and core types](#todo-bi-directional-type-mapping-primitives-and-core-types)
- [Bi-directional type mapping: primitives and core types](#bi-directional-type-mapping-primitives-and-core-types)
- [TODO: Integers](#todo-integers)
- [Character types](#character-types)
- [References](#references)
- [TODO: Advanced type mapping: pointers, references, and `const`](#todo-advanced-type-mapping-pointers-references-and-const)
- [TODO: Bi-directional type mapping: standard library types](#todo-bi-directional-type-mapping-standard-library-types)
- [TODO: The operator interoperability model](#todo-the-operator-interoperability-model)
@@ -206,7 +209,22 @@ fn Run() {
## TODO: Accessing global variables
## TODO: Bi-directional type mapping: primitives and core types
## Bi-directional type mapping: primitives and core types
### TODO: Integers
### Character types
Carbon's `char` type transparently maps to C++'s `char` type. Carbon's `char`
type is always unsigned. When compiling C++ using Carbon's toolchain, C++ `char`
is treated as `unsigned` by default (`-funsigned-char`). When interoperating
with a signed C++ `char` type (`-fno-unsigned-char`), Carbon will maintain
interoperability, though bits will be interpreted differently in each language.
#### References
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)
## TODO: Advanced type mapping: pointers, references, and `const`
@@ -28,6 +28,7 @@ A _lexical element_ is one of the following:
- a [numeric literal](numeric_literals.md)
- a [string literal](string_literals.md)
- a [character literal](character_literals.md)
- a [comment](comments.md)
- a [symbolic token](symbolic_tokens.md)
@@ -0,0 +1,68 @@
# Character literals
<!--
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
-->
<!-- toc -->
## Table of contents
- [Overview](#overview)
- [Details](#details)
- [Escape Sequences](#escape-sequences)
- [References](#references)
<!-- tocstop -->
## Overview
A character literal represents a single Unicode code point at compile time.
Character literals are delimited by single quotes (`'`), for example `'a'`.
```carbon
var a: char = 'a';
var newline: char = '\n';
```
## Details
A character literal consists of a sequence of characters enclosed in single
quotes (`'`).
- The contents must represent precisely one Unicode code point.
- Hex escape sequences (`\xHH`) are supported but limited to values up to
`0x7F` (where the UTF-8 code unit and Unicode code point values are
identical). Values `0x80` and above are disallowed in character literals to
avoid ambiguity between arbitrary byte values and Unicode code points.
- Grapheme clusters (sequences of multiple code points representing a single
visual character) are **not** supported in character literals.
### Escape Sequences
Character literals support the same escape sequences as
[string literals](string_literals.md#escape-sequences):
| Escape | Meaning |
| ------------- | ------------------------------------------------------------------- |
| `\t` | U+0009 CHARACTER TABULATION |
| `\n` | U+000A LINE FEED |
| `\r` | U+000D CARRIAGE RETURN |
| `\"` | U+0022 QUOTATION MARK (`"`) |
| `\'` | U+0027 APOSTROPHE (`'`) |
| `\\` | U+005C REVERSE SOLIDUS (`\`) |
| `\0` | Code unit with value 0 |
| `\xHH` | Code unit with hexadecimal value HH<sub>16</sub>(limited to ≤ `7F`) |
| `\u{HHHH...}` | Unicode code point U+HHHH... |
Hexadecimal digits (`H`) in `\x` or `\u` escape sequences must use uppercase
letters (for example, `\x0A`, not `\x0a`).
## References
- Proposal
[#1964: Character Literals](https://github.com/carbon-language/carbon-lang/pull/1964)
- Proposal
[#6710: `char` redesign](https://github.com/carbon-language/carbon-lang/pull/6710)