Где реализованы Rust boolean и другие примитивные типы?

Я просматривал код за некоторыми из основных типов в Rust, например. приятная простая реализация Option<T> или странная макромагия за tuple, и я смог найти все типы, которые я хотел в libcore. Все, кроме одного - bool. Я не мог найти его нигде.

Где находится код bool в Rust? Я знаю, что это не самый новый тип, но я был удивлен, что не смог его найти.

Благодаря ответам Фрэнсиса и Родриго я заметил, что код, который я нашел для других примитивов, был только их чертами и связанными макросами, но не фактическими реализациями.

В книге Rust указано, что примитивы встроены в язык, но я не удовлетворен этим объяснением. Когда они были построены? Может ли это быть прослежено до того момента, когда компилятор Rust впервые был создан с помощью Rust или это произошло, когда оно все еще было встроено в OCaml? Существует ли какой-либо соответствующий код?

Ответ 1

Итак, вот немного больше информации о том, что происходит в компиляторе. Для начала, как уже упоминалось, фактические операции, выполняемые с помощью логических элементов, полностью обрабатываются LLVM и непосредственно передаются в соответствующие инструкции ЦП. Хотя есть некоторые случаи, когда код просто волшебным образом появляется из-за начальной загрузки, это не один из них. Компилятор специально написан для обработки этих типов и испускает правильные инструкции LLVM.

Для самых ранних частей компиляции (например, при макрорасширении) тип bool не является особым. Это всего лишь некоторый путь с идентификатором bool. В конце концов здесь, он преобразуется в примитивный тип. Фактическое определение типа здесь.

Итак, посмотрим, как работает оператор !. Как я упоминал ранее, код в libcore, который делает impl Not for bool, никогда не используется. Код в форме !expr преобразуется в <T as Not>::not(expr) здесь. Однако вы заметите, что он проверяет, действительно ли это конкретное выражение является вызовом метода или нет, и просто оставляет его как !expr, если он не предназначен для вызова метода. Как это знать? Вызов в MIR - это просто поиск в кеше. Кэш заселен во время проверки проверки типа. Здесь, где происходит вставка кеша - в основном проверка того, реализуется ли признак Not для заданного типа в любое время, когда он видит !. И вы заметите, что эта строка специально исключает логические и интегральные типы, которые в конечном итоге сводятся к инструкциям LLVM напрямую.

Это грубая картина того, как она определена. Вы найдете аналогичный код в тех же файлах для других примитивов. Теоретически может быть какая-то строка где-то, которая была enum bool { true, false }, но в конечном итоге этот же код все равно должен был бы переопределить его и исправить соответствующие внутренние свойства LLVM, и целые числа не могли быть представлены таким образом.

Ответ 2

bool - это примитивный тип. Примитивные типы и операции над ними реализуются компилятором, то есть компилятор испускает специализированный код для выполнения операций над примитивными типами.

Вы увидите, что bool реализует многие черты. Эти реализации исходят из libcore, но они часто реализуются с помощью соответствующего оператора. Например, Not::not реализуется путем возврата !self. Для любого не-примитивного типа это вызовет рекурсию Not::not и вызовет переполнение стека, но для примитивных типов компилятор по-разному решает оператор, и эти реализации признаков предоставляются только в интересах общего кода.

Ответ 3

Вы можете определить определение core::i32 только из-за констант i32::MIN и i32::MAX. Фактический тип - это просто псевдоним для встроенного типа i32.

В случае core::f32, например, имеется много полезных констант.

Но для bool нет полезных значений, кроме true и false, которые являются ключевыми словами, поэтому нет источника для bool.