So here's a bit more information about what goes on in the compiler. For starters, as has already been mentioned, the actual operations that occur with booleans are entirely handled by LLVM, and get directly translated to the corresponding CPU instructions. While there are some cases where code just magically appears due to bootstrapping, this is not one of them. The compiler is specifically written to handle these types and emit the correct LLVM instructions.
For the earliest parts of compilation (e.g. during macro expansion) the type bool
isn't special. It's just some path with the identifier bool
. Eventually around here it will get converted to a primitive type. The actual definition of the type is here.
So now let's look at how the !
operator works. As I mentioned earlier, the code in libcore that does impl Not for bool
never gets used. Code in the form !expr
gets transformed into <T as Not>::not(expr)
here. However, you'll notice that it checks to see if this particular expression is in fact a method call or not, and just leaves it as !expr
if it's not meant to be a method call. How does it know? The call in MIR is just a cache lookup. The cache got populated during the type checking pass. Here is where the cache insertion occurs -- basically checking to see if the Not
trait is implemented for a given type any time it sees a !
. And you'll notice that this line specifically excludes booleans and integral types, which end up compiling down to LLVM instructions directly.
That's the rough picture of how it's defined. You'll find similar code in the same files for other primitives. In theory there could be some line somewhere that was enum bool { true, false }
-- but ultimately this same code would still need to override it and emit the appropriate LLVM intrinsics, and integers couldn't be represented this way.
i1
(i8
) in LLVM bitcode, and before that it's probably anenum
in some Rust IR. Going lower down, you get to logic gates and transistors and electrons. Which of those is an "actual implementation"? – Goalie==
operator (i.e. boolean logic). I'm not too savvy with writing compilers so my wording might not be perfect, but I think there must have been a stage where the primitives were first "embedded" in the rustc compiler so it was able to compile them down to LLVM. – Evenfall