In addition to all the great answers so far:
You have an "observer bias". You don't observe bugs, and therefore you assume that there aren't any.
I used to think like you do. Then I started writing compilers professionally, and let me tell you, there are lots of bugs in there!
You don't see the bugs because you write code that is just like 99.999% of all the rest of the code that people write. You probably write perfectly normal, straightforward, clearly correct code that calls methods and runs loops and doesn't do anything fancy or weird, because you're a normal developer solving normal business problems.
You don't see any compiler bugs because the compiler bugs aren't in the easy-to-analyze straightforward normal code scenarios; the bugs are in the analysis of weird code that you don't write.
I on the other hand have the opposite observer bias. I see crazy code all day every day, and so to me the compilers seems to be chock full of bugs.
If you sat down with the language specification of any language, and took any compiler implementation for that language, and really tried hard to determine whether the compiler exactly implemented the spec or not, concentrating on obscure corner cases, pretty soon you'd be finding compiler bugs quite frequently. Let me give you an example, here's a C# compiler bug I found literally five minutes ago.
static void N(ref int x){}
...
N(ref 123);
The compiler gives three errors.
- A ref or out argument must be an assignable variable.
- The best match for N(ref int x) has invalid arguments.
- Missing "ref" on argument 1.
Obviously the first error message is correct and the third one is a bug. The error generation algorithm is trying to figure out why the first argument was invalid, it looks at it, sees that it is a constant, and does not go back to the source code to check whether it was marked as "ref"; rather, it assumes that no one would be foolish enough to mark a constant as ref, and decides that the ref must be missing.
It's not clear what the correct third error message is, but this isn't it. In fact, it is not clear if the second error message is correct either. Should overload resolution fail, or should "ref 123" be treated as a ref argument of the correct type? I'll now have to give it some thought and talk it over with the triage team so that we can determine what the correct behaviour is.
You've never seen this bug because you would probably never do something so silly as to try to pass 123 by ref. And if you did, you probably wouldn't even notice that the third error message is nonsensical, since the first one is correct and sufficient to diagnose the problem. But I do try to do stuff like that, because I'm trying to break the compiler. If you tried, you'd see the bugs too.