Выражения-литералы
Syntax
LiteralExpression →
CHAR_LITERAL
| STRING_LITERAL
| RAW_STRING_LITERAL
| BYTE_LITERAL
| BYTE_STRING_LITERAL
| RAW_BYTE_STRING_LITERAL
| C_STRING_LITERAL
| RAW_C_STRING_LITERAL
| INTEGER_LITERAL
| FLOAT_LITERAL
| true
| false
Выражение-литерал — это выражение, состоящее из одного токена, а не из последовательности токенов, которое непосредственно и прямо обозначает значение, к которому оно вычисляется, а не ссылается на него по имени или по какому-либо другому правилу вычисления.
Литерал является формой константного выражения, поэтому вычисляется (в основном) во время компиляции.
Каждая из лексических форм литеральных токенов, описанных ранее, может составлять выражение-литерал, как и ключевые слова true и false.
#![allow(unused)] fn main() { "hello"; // строковый тип '5'; // символьный тип 5; // целочисленный тип }
В приведенных ниже описаниях строковое представление токена — это последовательность символов из входных данных, которая соответствует продукции токена в грамматике Лексера.
Note
Это строковое представление никогда не включает символ
U+000D(CR), за которым сразу следуетU+000A(LF): эта пара была бы ранее преобразована в одинU+000A(LF).
Экранирования
В описаниях текстовых выражений-литералов ниже используются несколько форм экранирования.
Каждая форма экранирования характеризуется:
- последовательностью экранирования: последовательностью символов, которая всегда начинается с
U+005C(\) - экранированным значением: либо одним символом, либо пустой последовательностью символов
В определениях экранирований ниже:
- Восьмеричная цифра — это любой из символов в диапазоне [
0-7]. - Шестнадцатеричная цифра — это любой из символов в диапазонах [
0-9], [a-f] или [A-F].
Простые экранирования
Каждая последовательность символов, встречающаяся в первом столбце следующей таблицы, является последовательностью экранирования.
В каждом случае экранированное значение — это символ, указанный в соответствующей записи во втором столбце.
| Последовательность | Экранированное значение |
|---|---|
\0 | U+0000 (NUL) |
\t | U+0009 (HT) |
\n | U+000A (LF) |
\r | U+000D (CR) |
\" | U+0022 (КАВЫЧКА) |
\' | U+0027 (АПОСТРОФ) |
\\ | U+005C (ОБРАТНАЯ КОСАЯ ЧЕРТА) |
8-битные экранирования
Последовательность экранирования состоит из \x, за которым следуют две шестнадцатеричные цифры.
Экранированное значение — это символ, скалярное значение Юникода которого является результатом интерпретации последних двух символов в последовательности экранирования как шестнадцатеричного целого числа, как если бы с помощью u8::from_str_radix с основанием 16.
Note
Таким образом, экранированное значение имеет скалярное значение Юникода в диапазоне
u8.
7-битные экранирования
Последовательность экранирования состоит из \x, за которым следуют восьмеричная цифра, а затем шестнадцатеричная цифра.
Экранированное значение — это символ, скалярное значение Юникода которого является результатом интерпретации последних двух символов в последовательности экранирования как шестнадцатеричного целого числа, как если бы с помощью u8::from_str_radix с основанием 16.
Юникодные экранирования
Последовательность экранирования состоит из \u{, за которым следует последовательность символов, каждый из которых является шестнадцатеричной цифрой или _, а затем }.
Экранированное значение — это символ, скалярное значение Юникода которого является результатом интерпретации шестнадцатеричных цифр, содержащихся в последовательности экранирования, как шестнадцатеричного целого числа, как если бы с помощью u32::from_str_radix с основанием 16.
Note
Разрешенные формы токенов CHAR_LITERAL или STRING_LITERAL гарантируют, что такой символ существует.
Экранирования продолжения строки
Последовательность экранирования состоит из \, за которым сразу следует U+000A (LF), и всех последующих пробельных символов до следующего непробельного символа.
Для этой цели пробельными символами являются U+0009 (HT), U+000A (LF), U+000D (CR) и U+0020 (SPACE).
Экранированное значение представляет собой пустую последовательность символов.
Note
Эффект этой формы экранирования заключается в том, что продолжение строки пропускает последующие пробелы, включая дополнительные переводы строк. Таким образом,
a,bиcравны:#![allow(unused)] fn main() { let a = "foobar"; let b = "foo\ bar"; let c = "foo\ bar"; assert_eq!(a, b); assert_eq!(b, c); }Пропуск дополнительных переводов строк (как в примере c) потенциально сбивает с толку и является неожиданным. Это поведение может быть изменено в будущем. Пока решение не принято, рекомендуется избегать зависимости от пропуска нескольких переводов строк с помощью продолжений строк. Дополнительную информацию смотрите в этом issue.
Символьные выражения-литералы
Символьное выражение-литерал состоит из одного токена CHAR_LITERAL.
Тип выражения — примитивный тип char.
Токен не должен иметь суффикса.
Содержимое литерала токена — это последовательность символов, следующая за первым U+0027 (') и предшествующая последнему U+0027 (') в строковом представлении токена.
Представленный символ выражения-литерала получается из содержимого литерала следующим образом:
- Если содержимое литерала является одной из следующих форм последовательности экранирования, то представленный символ — это экранированное значение последовательности экранирования:
- В противном случае представленный символ — это единственный символ, составляющий содержимое литерала.
Значением выражения является char, соответствующий скалярному значению Юникода представленного символа.
Note
Разрешенные формы токена CHAR_LITERAL гарантируют, что эти правила всегда производят один символ.
Примеры символьных выражений-литералов:
#![allow(unused)] fn main() { 'R'; // R '\''; // ' '\x52'; // R '\u{00E6}'; // LATIN SMALL LETTER AE (U+00E6) }
Строковые выражения-литералы
Строковое выражение-литерал состоит из одного токена STRING_LITERAL или RAW_STRING_LITERAL.
Тип выражения — разделяемая ссылка (со временем жизни static) на примитивный тип str.
То есть тип — &'static str.
Токен не должен иметь суффикса.
Содержимое литерала токена — это последовательность символов, следующая за первым U+0022 (") и предшествующая последнему U+0022 (") в строковом представлении токена.
Представленная строка выражения-литерала — это последовательность символов, полученная из содержимого литерала следующим образом:
-
Если токен является STRING_LITERAL, каждая последовательность экранирования любой из следующих форм, встречающаяся в содержимом литерала, заменяется экранированным значением последовательности экранирования.
- Простые экранирования
- 7-битные экранирования
- Юникодные экранирования
- Экранирования продолжения строки
Эти замены происходят в порядке слева направо. Например, токен
"\\x41"преобразуется в символы\x41.
- Если токен является RAW_STRING_LITERAL, представленная строка идентична содержимому литерала.
Значением выражения является ссылка на статически выделенный str, содержащий UTF-8 кодировку представленной строки.
Примеры строковых выражений-литералов:
#![allow(unused)] fn main() { "foo"; r"foo"; // foo "\"foo\""; r#""foo""#; // "foo" "foo #\"# bar"; r##"foo #"# bar"##; // foo #"# bar "\x52"; "R"; r"R"; // R "\\x52"; r"\x52"; // \x52 }
Байтовые выражения-литералы
Байтовое выражение-литерал состоит из одного токена BYTE_LITERAL.
Тип выражения — примитивный тип u8.
Токен не должен иметь суффикса.
Содержимое литерала токена — это последовательность символов, следующая за первым U+0027 (') и предшествующая последнему U+0027 (') в строковом представлении токена.
Представленный символ выражения-литерала получается из содержимого литерала следующим образом:
- Если содержимое литерала является одной из следующих форм последовательности экранирования, то представленный символ — это экранированное значение последовательности экранирования:
- В противном случае представленный символ — это единственный символ, составляющий содержимое литерала.
Значением выражения является скалярное значение Юникода представленного символа.
Note
Разрешенные формы токена BYTE_LITERAL гарантируют, что эти правила всегда производят один символ, чье скалярное значение Юникода находится в диапазоне
u8.
Примеры байтовых выражений-литералов:
#![allow(unused)] fn main() { b'R'; // 82 b'\''; // 39 b'\x52'; // 82 b'\xA0'; // 160 }
Байтовые строковые выражения-литералы
Байтовое строковое выражение-литерал состоит из одного токена BYTE_STRING_LITERAL или RAW_BYTE_STRING_LITERAL.
Тип выражения — разделяемая ссылка (со временем жизни static) на массив, тип элемента которого — u8.
То есть тип — &'static [u8; N], где N — количество байт в представленной строке, описанной ниже.
Токен не должен иметь суффикса.
Содержимое литерала токена — это последовательность символов, следующая за первым U+0022 (") и предшествующая последнему U+0022 (") в строковом представлении токена.
Представленная строка выражения-литерала — это последовательность символов, полученная из содержимого литерала следующим образом:
-
Если токен является BYTE_STRING_LITERAL, каждая последовательность экранирования любой из следующих форм, встречающаяся в содержимом литерала, заменяется экранированным значением последовательности экранирования.
Эти замены происходят в порядке слева направо. Например, токен
b"\\x41"преобразуется в символы\x41.
- Если токен является RAW_BYTE_STRING_LITERAL, представленная строка идентична содержимому литерала.
Значением выражения является ссылка на статически выделенный массив, содержащий скалярные значения Юникода символов в представленной строке, в том же порядке.
Note
Разрешенные формы токенов BYTE_STRING_LITERAL и RAW_BYTE_STRING_LITERAL гарантируют, что эти правила всегда производят значения элементов массива в диапазоне
u8.
Примеры байтовых строковых выражений-литералов:
#![allow(unused)] fn main() { b"foo"; br"foo"; // foo b"\"foo\""; br#""foo""#; // "foo" b"foo #\"# bar"; br##"foo #"# bar"##; // foo #"# bar b"\x52"; b"R"; br"R"; // R b"\\x52"; br"\x52"; // \x52 }
Строковые выражения-литералы в стиле C
Строковое выражение-литерал в стиле C состоит из одного токена C_STRING_LITERAL или RAW_C_STRING_LITERAL.
Тип выражения — разделяемая ссылка (со временем жизни static) на тип CStr из стандартной библиотеки.
То есть тип — &'static core::ffi::CStr.
Токен не должен иметь суффикса.
Содержимое литерала токена — это последовательность символов, следующая за первым " и предшествующая последнему " в строковом представлении токена.
Представленные байты выражения-литерала — это последовательность байтов, полученная из содержимого литерала следующим образом:
- Если токен является C_STRING_LITERAL, содержимое литерала обрабатывается как последовательность элементов, каждый из которых представляет собой либо один символ Юникода, отличный от
\, либо экранирование. Последовательность элементов преобразуется в последовательность байтов следующим образом:- Каждый отдельный символ Юникода вносит свой UTF-8 representation.
- Каждое простое экранирование вносит скалярное значение Юникода своего экранированного значения.
- Каждое 8-битное экранирование вносит один байт, содержащий скалярное значение Юникода своего экранированного значения.
- Каждое юникодное экранирование вносит UTF-8 representation своего экранированного значения.
- Каждое экранирование продолжения строки не вносит байтов.
- Если токен является RAW_C_STRING_LITERAL, представленные байты — это UTF-8 кодировка содержимого литерала.
Note
Разрешенные формы токенов C_STRING_LITERAL и RAW_C_STRING_LITERAL гарантируют, что представленные байты никогда не включают нулевой байт.
Значением выражения является ссылка на статически выделенный CStr, чей массив байтов содержит представленные байты, за которыми следует нулевой байт.
Примеры строковых выражений-литералов в стиле C:
#![allow(unused)] fn main() { c"foo"; cr"foo"; // foo c"\"foo\""; cr#""foo""#; // "foo" c"foo #\"# bar"; cr##"foo #"# bar"##; // foo #"# bar c"\x52"; c"R"; cr"R"; // R c"\\x52"; cr"\x52"; // \x52 c"æ"; // LATIN SMALL LETTER AE (U+00E6) c"\u{00E6}"; // LATIN SMALL LETTER AE (U+00E6) c"\xC3\xA6"; // LATIN SMALL LETTER AE (U+00E6) c"\xE6".to_bytes(); // [230] c"\u{00E6}".to_bytes(); // [195, 166] }
Целочисленные выражения-литералы
Целочисленное выражение-литерал состоит из одного токена INTEGER_LITERAL.
Если токен имеет суффикс, этот суффикс должен быть именем одного из примитивных целочисленных типов: u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize или isize, и выражение имеет этот тип.
Если токен не имеет суффикса, тип выражения определяется выводом типа:
- Если целочисленный тип может быть однозначно определен из окружающего контекста программы, выражение имеет этот тип.
- Если контекст программы недостаточно ограничивает тип, по умолчанию используется знаковый 32-битный целочисленный тип
i32.
- Если контекст программы чрезмерно ограничивает тип, это считается статической ошибкой типа.
Примеры целочисленных выражений-литералов:
#![allow(unused)] fn main() { 123; // тип i32 123i32; // тип i32 123u32; // тип u32 123_u32; // тип u32 let a: u64 = 123; // тип u64 0xff; // тип i32 0xff_u8; // тип u8 0o70; // тип i32 0o70_i16; // тип i16 0b1111_1111_1001_0000; // тип i32 0b1111_1111_1001_0000i64; // тип i64 0usize; // тип usize }
Значение выражения определяется из строкового представления токена следующим образом:
-
Выбирается целочисленное основание системы счисления путем проверки первых двух символов строки, следующим образом:
0bуказывает основание 20oуказывает основание 80xуказывает основание 16- в противном случае основание равно 10.
- Если основание не 10, первые два символа удаляются из строки.
- Любой суффикс удаляется из строки.
- Любые подчеркивания удаляются из строки.
- Строка преобразуется в значение
u128как если бы с помощьюu128::from_str_radixс выбранным основанием. Если значение не помещается вu128, это ошибка компилятора.
- Значение
u128преобразуется в тип выражения через числовое приведение.
Note
Финальное приведение будет усекать значение литерала, если оно не помещается в тип выражения.
rustcвключает проверку переполнения литералов с именемoverflowing_literals, по умолчаниюdeny, которая отклоняет выражения, где это происходит.
Note
-1i8, например, это применение оператора отрицания к выражению-литералу1i8, а не одиночное целочисленное выражение-литерал. См. Переполнение для примечаний о представлении наименьшего отрицательного значения для знакового типа.
Выражения-литералы с плавающей точкой
Выражение-литерал с плавающей точкой имеет одну из двух форм:
- одиночный токен FLOAT_LITERAL
- одиночный токен INTEGER_LITERAL, который имеет суффикс и не имеет индикатора системы счисления
Если токен имеет суффикс, этот суффикс должен быть именем одного из примитивных типов с плавающей точкой: f32 или f64, и выражение имеет этот тип.
Если токен не имеет суффикса, тип выражения определяется выводом типа:
- Если тип с плавающей точкой может быть однозначно определен из окружающего контекста программы, выражение имеет этот тип.
- Если контекст программы недостаточно ограничивает тип, по умолчанию используется
f64.
- Если контекст программы чрезмерно ограничивает тип, это считается статической ошибкой типа.
Примеры выражений-литералов с плавающей точкой:
#![allow(unused)] fn main() { 123.0f64; // тип f64 0.1f64; // тип f64 0.1f32; // тип f32 12E+99_f64; // тип f64 5f32; // тип f32 let x: f64 = 2.; // тип f64 }
Значение выражения определяется из строкового представления токена следующим образом:
- Любой суффикс удаляется из строки.
- Любые подчеркивания удаляются из строки.
- Строка преобразуется в тип выражения как если бы с помощью
f32::from_strилиf64::from_str.
Note
-1.0, например, это применение оператора отрицания к выражению-литералу1.0, а не одиночное выражение-литерал с плавающей точкой.
Note
infиNaNне являются литеральными токенами. Вместо выражений-литералов можно использовать константыf32::INFINITY,f64::INFINITY,f32::NANиf64::NAN. Вrustcлитерал, достаточно большой, чтобы быть оцененным как бесконечность, вызовет проверку переполнения литераловoverflowing_literals.
Логические выражения-литералы
Логическое выражение-литерал состоит из одного из ключевых слов true или false.
Тип выражения — примитивный логический тип, и его значение:
- true, если ключевое слово
true - false, если ключевое слово
false