2016-09-05 2 views
12

Я просматривал код за некоторыми из основных типов в Rust, например. pleasantly simple implementation от Option<T> или weird macro magic позади tuple, и я смог найти все типы, которые я хотел в libcore. Все, кроме одного - bool. Я не мог найти его нигде.Где реализованы булевские и другие примитивные типы Rust?

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

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

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

+0

Что именно вы ищете? В какой-то момент «логическое» - это всего лишь один бит на процессоре (или полный байт по соображениям производительности). До этого это 'i1' (' i8') в биткоде LLVM, и до этого это, вероятно, 'enum' в некотором Rust IR. Двигаясь ниже, вы попадаете в логические ворота, транзисторы и электроны. Какая из них является «фактической реализацией»? – Shepmaster

+1

Я ищу место, где язык Rust (не бит Lode LLVM или CPU) начал распознавать, например. оператор '==' (т. е. логическая логика). Я не слишком разбираюсь в написании компиляторов, поэтому моя формулировка может быть не идеальной, но я думаю, что, должно быть, был этап, когда примитивы были сначала «встроены» в компилятор rustc, чтобы он смог скомпилировать их в LLVM. – ljedrz

ответ

13

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

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

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

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

11

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

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

+0

«array» также является примитивным, но [его реализация] (https://github.com/rust-lang/rust/blob/100b309fd1b951fa074556f9e3a50354d1ed7923/src/libcore/array.rs) можно легко найти. Сначала я надеялся найти 'bool' кодом для' not', но не повезло. – ljedrz

+0

Чтобы быть справедливым, код 'array' - это макро магия, поэтому это может быть не« реальная »реализация, как вы имели в виду. – ljedrz

+2

Вы найдете реализации _traits_ для примитивных типов (на самом деле вы можете определить признак в ящике и реализовать его для примитивного типа самостоятельно), но вы никогда не найдете _definition_ примитивных типов в любой библиотеке. –

3

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

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

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

+0

Это имеет смысл, но, должно быть, оно было введено _somehow_. – ljedrz

+0

@ljedrz: Это точно так же, как 'i32'. Он не вводится в 'core', он является внутренним типом, определенным непосредственно компилятором. Часть «core» - это всего лишь дополнительные части вокруг этого типа. – rodrigo

+0

Как это работает? Я скорректировал этот вопрос, поскольку естественным продолжением этого ответа является «как это возможно?». rustc построен из кода в [github] (https://github.com/rust-lang/rust), поэтому, если он определен непосредственно компилятором, как его там нет? – ljedrz

Смежные вопросы