Problems no program can solve
Wouldn't it be useful to have a tool that reads any program and its input and tells you whether it will ever finish? Your editor could warn about infinite loops before you run anything. Turing proved in 1936 that no such tool can exist — not because we haven't been clever enough, but because the idea contradicts itself. That's the halting problem, and it was one of the first results in computer science.
A problem is decidable if some Turing machine always halts with the right yes-or-no answer. Everything from Unit 1 is decidable. The halting problem is not, and neither are many questions about programs that follow from it.
The diagonal argument
The proof uses a trick from Georg Cantor (1891). Write a list of binary strings, one per row. Build a new string by taking the i-th character of row i and flipping it. The new string differs from row 0 at position 0, from row 1 at position 1, and so on — so it can't equal any row. Whatever list you start with, the diagonal argument builds something missing from it.
diagonal(["000", "111", "010"]) // row 0, char 0: 0 → 1 // row 1, char 1: 1 → 0 // row 2, char 2: 0 → 1 // "101" — not in the list
Cantor used this to show there are more real numbers than whole numbers. Turing used it on programs: list every program, and build one that disagrees with each of them.