Skip to content

Commit a3deca4

Browse files
authored
Rollup merge of rust-lang#93493 - GKFX:char-docs-2, r=scottmcm
Document valid values of the char type As discussed at rust-lang#93392, the current documentation on what constitutes a valid char isn't very detailed and is partly on the MAX constant rather than the type itself. This PR expands on that information, stating the actual numerical range, giving examples of what won't work, and also mentions how a `char` might be a valid USV but still not be a defined character (terminology checked against [Unicode 14.0, table 2-3](https://www.unicode.org/versions/Unicode14.0.0/ch02.pdf#M9.61673.TableTitle.Table.22.Types.of.Code.Points)).
2 parents 2484cb8 + d372baf commit a3deca4

File tree

2 files changed

+108
-10
lines changed

2 files changed

+108
-10
lines changed

library/core/src/primitive_docs.rs

+54-5
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,69 @@ mod prim_bool {}
275275
mod prim_never {}
276276

277277
#[doc(primitive = "char")]
278+
#[allow(rustdoc::invalid_rust_codeblocks)]
278279
/// A character type.
279280
///
280281
/// The `char` type represents a single character. More specifically, since
281282
/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
282-
/// scalar value]', which is similar to, but not the same as, a '[Unicode code
283-
/// point]'.
284-
///
285-
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
286-
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
283+
/// scalar value]'.
287284
///
288285
/// This documentation describes a number of methods and trait implementations on the
289286
/// `char` type. For technical reasons, there is additional, separate
290287
/// documentation in [the `std::char` module](char/index.html) as well.
291288
///
289+
/// # Validity
290+
///
291+
/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]'
292+
/// other than a [surrogate code point]. This has a fixed numerical definition:
293+
/// code points are in the range 0 to 0x10FFFF, inclusive.
294+
/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF.
295+
///
296+
/// No `char` may be constructed, whether as a literal or at runtime, that is not a
297+
/// Unicode scalar value:
298+
///
299+
/// ```compile_fail
300+
/// // Each of these is a compiler error
301+
/// ['\u{D800}', '\u{DFFF}', '\u{110000}'];
302+
/// ```
303+
///
304+
/// ```should_panic
305+
/// // Panics; from_u32 returns None.
306+
/// char::from_u32(0xDE01).unwrap();
307+
/// ```
308+
///
309+
/// ```no_run
310+
/// // Undefined behaviour
311+
/// unsafe { char::from_u32_unchecked(0x110000) };
312+
/// ```
313+
///
314+
/// USVs are also the exact set of values that may be encoded in UTF-8. Because
315+
/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store
316+
/// any `char` in a `str` or read any character from a `str` as a `char`.
317+
///
318+
/// The gap in valid `char` values is understood by the compiler, so in the
319+
/// below example the two ranges are understood to cover the whole range of
320+
/// possible `char` values and there is no error for a [non-exhaustive match].
321+
///
322+
/// ```
323+
/// let c: char = 'a';
324+
/// match c {
325+
/// '\0' ..= '\u{D7FF}' => false,
326+
/// '\u{E000}' ..= '\u{10FFFF}' => true,
327+
/// };
328+
/// ```
329+
///
330+
/// All USVs are valid `char` values, but not all of them represent a real
331+
/// character. Many USVs are not currently assigned to a character, but may be
332+
/// in the future ("reserved"); some will never be a character
333+
/// ("noncharacters"); and some may be given different meanings by different
334+
/// users ("private use").
335+
///
336+
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
337+
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
338+
/// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive
339+
/// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point
340+
///
292341
/// # Representation
293342
///
294343
/// `char` is always four bytes in size. This is a different representation than

library/std/src/primitive_docs.rs

+54-5
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,69 @@ mod prim_bool {}
275275
mod prim_never {}
276276

277277
#[doc(primitive = "char")]
278+
#[allow(rustdoc::invalid_rust_codeblocks)]
278279
/// A character type.
279280
///
280281
/// The `char` type represents a single character. More specifically, since
281282
/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
282-
/// scalar value]', which is similar to, but not the same as, a '[Unicode code
283-
/// point]'.
284-
///
285-
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
286-
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
283+
/// scalar value]'.
287284
///
288285
/// This documentation describes a number of methods and trait implementations on the
289286
/// `char` type. For technical reasons, there is additional, separate
290287
/// documentation in [the `std::char` module](char/index.html) as well.
291288
///
289+
/// # Validity
290+
///
291+
/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]'
292+
/// other than a [surrogate code point]. This has a fixed numerical definition:
293+
/// code points are in the range 0 to 0x10FFFF, inclusive.
294+
/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF.
295+
///
296+
/// No `char` may be constructed, whether as a literal or at runtime, that is not a
297+
/// Unicode scalar value:
298+
///
299+
/// ```compile_fail
300+
/// // Each of these is a compiler error
301+
/// ['\u{D800}', '\u{DFFF}', '\u{110000}'];
302+
/// ```
303+
///
304+
/// ```should_panic
305+
/// // Panics; from_u32 returns None.
306+
/// char::from_u32(0xDE01).unwrap();
307+
/// ```
308+
///
309+
/// ```no_run
310+
/// // Undefined behaviour
311+
/// unsafe { char::from_u32_unchecked(0x110000) };
312+
/// ```
313+
///
314+
/// USVs are also the exact set of values that may be encoded in UTF-8. Because
315+
/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store
316+
/// any `char` in a `str` or read any character from a `str` as a `char`.
317+
///
318+
/// The gap in valid `char` values is understood by the compiler, so in the
319+
/// below example the two ranges are understood to cover the whole range of
320+
/// possible `char` values and there is no error for a [non-exhaustive match].
321+
///
322+
/// ```
323+
/// let c: char = 'a';
324+
/// match c {
325+
/// '\0' ..= '\u{D7FF}' => false,
326+
/// '\u{E000}' ..= '\u{10FFFF}' => true,
327+
/// };
328+
/// ```
329+
///
330+
/// All USVs are valid `char` values, but not all of them represent a real
331+
/// character. Many USVs are not currently assigned to a character, but may be
332+
/// in the future ("reserved"); some will never be a character
333+
/// ("noncharacters"); and some may be given different meanings by different
334+
/// users ("private use").
335+
///
336+
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
337+
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
338+
/// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive
339+
/// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point
340+
///
292341
/// # Representation
293342
///
294343
/// `char` is always four bytes in size. This is a different representation than

0 commit comments

Comments
 (0)