Compilers Interview Guide
What each question actually discriminates, what a strong answer covers, and the specific plausible-sounding wrong answers a confident candidate really gives.
TestsWhether the candidate carries a staged model of compilation or one opaque box — and, more discriminating, whether they know their model describes one implementation rather than all of them. Almost everyone can list phases; far fewer can say which phases their favourite language actually has.
TestsWhether the candidate understands that structure is the thing being computed, not a convenience. The discriminating detail is whether they can name a question that a flat token list *cannot* answer at all, as opposed to one it answers awkwardly.
TestsWhether the candidate can state what a type system actually proves, versus what people hope it proves. The tell is precision about scope: a strong candidate volunteers the properties their type system does *not* model before being asked.
TestsWhether the candidate can connect a representation choice to the cost of the analyses built on it. The discriminator is whether they can name an analysis that becomes trivial and say what it used to cost.
TestsWhether the candidate reasons about optimization as a budget rather than a good deed. The discriminator is whether they can name a case where inlining makes the program measurably slower, not merely bigger.
TestsWhether the candidate understands that the JIT's advantage is *information*, not cleverness — and whether they immediately supply the other half of the ledger. A candidate who only says "it can specialize" has half an answer.
TestsWhether the candidate understands undefined behavior as a licence the optimizer holds rather than as an outcome the program suffers. The discriminator is whether they can trace a transformation from the assumption to the deleted code.
TestsWhether the candidate knows what a spill is and can reason about which value to spill. Anyone can say "it uses memory"; the discriminator is the choice function and the fact that spilling changes the problem it was solving.
TestsWhether the candidate has a model of separate compilation at all. The discriminating detail is relocation: candidates who have only read about linking say "it joins the files"; candidates who have debugged a link error know addresses had to be patched.
TestsWhether the candidate has a category error baked in. This is the single most reliable question in the bank because the wrong answer is the one almost everybody was taught, and the recovery — noticing that the question presupposes something false — is the signal.
TestsWhether the candidate can recognise ambiguity as a property of the grammar rather than a bug in the parser, and whether they know the two distinct ways to remove it and what each costs.
TestsWhether the candidate knows that lexing is greedy by rule rather than by intent, and can predict the consequence when the greedy choice is the wrong one. It also separates people who have written a lexer from people who have read about one.
TestsWhether the candidate weighs parsing techniques by engineering consequences — diagnostics, maintainability, grammar flexibility — rather than by expressive power alone. Nearly everyone knows LR is more powerful; the discriminator is whether they know why hand-written recursive descent won in practice.
TestsWhether the candidate has a working model of scope as a structure the compiler builds, not a rule it applies. The discriminator is whether they realise the answer is a data structure with a lifetime, and can say what happens after resolution.
TestsWhether the candidate can describe inference as constraint generation plus solving rather than as guessing, and whether they know the specific features that break complete inference. Naming the occurs check is a strong signal; naming why subtyping complicates inference is stronger.
TestsWhether the candidate can derive variance from mutability instead of memorising a rule. The discriminator is whether they reach for the counterexample — writing a Cat into the list — rather than reciting "generics are invariant".
TestsWhether the candidate can trade code size against runtime cost with real numbers in mind, and whether they know which choice their language made and what it forced on the rest of the design.
TestsWhether the candidate can state a graph property precisely and then name a transformation whose legality depends on it. Reciting the definition is common; connecting it to a specific pass is not.
TestsWhether the candidate sees the framework or four unrelated algorithms. The discriminator is whether they can place a new analysis into the framework on the spot by naming its direction and meet operator.
TestsWhether the candidate reasons from observable behavior and preconditions instead of from "it looks the same". The discriminator is whether they name the trap and the exception cases without prompting — those are what separate an optimizer from a miscompiler.
TestsWhether the candidate understands that most missed optimizations in real code are memory questions the compiler could not answer, and can name the mechanisms languages provide to answer them.
TestsWhether the candidate knows there is a contract there at all, and can predict the failure mode. The discriminator is that ABI mismatches do not produce clean errors, and a candidate who expects one has never debugged a real one.
TestsWhether the candidate can argue both directions. Most people have one strong opinion here; the discriminator is whether they can state the case against their own position and name a concrete failure it causes.
TestsWhether the candidate understands speculation as a two-part mechanism — the assumption and the escape route — and can describe the state reconstruction. This is the question that separates people who have used a JIT from people who have worked on one.
TestsWhether the candidate understands debug information as a separate artifact with its own correctness problem, and knows that every transformation in the chain has to maintain it or the mapping degrades.
TestsWhether the candidate can reason about dependency granularity and correctness, not just timestamps. The discriminator is whether they raise the two failure directions — rebuilding too much and rebuilding too little — and know which one is dangerous.
TestsWhether the candidate can separate two orthogonal things people habitually confuse — seeing more code versus knowing more about execution — and whether they know what a bad profile costs.
TestsWhether the candidate prices the whole thing rather than the parser. Everyone can write a parser in a weekend; the discriminator is whether they know what the second year costs.
TestsWhether the candidate can name what the AST is bad at, rather than repeating the M-frontends-times-N-backends argument. That argument is correct and everyone has it; the discriminator is the analysis argument underneath.
TestsWhether the candidate can transfer compiler discipline to a new setting rather than reaching for prompt engineering. The discriminator is whether they put the checks before execution rather than in a retry loop.