Ответ 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, и целые числа не могли быть представлены таким образом.