You can solve the "90%" problem statically. My Ruby-compiler-in-progress warns of methods that have not been seen, and I may eventually add some (entirely optional) pragma to allow hinting to reduce false positives (though getting that non-intrusive will be a fun challenge).
But you are right, the general case does require a solution to the halting problem, something which is trivial to demonstrate very explicitly:
eval(STDIN.gets)
42.will_i_halt?
Put that in a file, and run it. Press enter, and it halts. Or cut and paste something like this, and it doesn't:
class Fixnum; def will_i_halt?; loop {}; end; end
And consider that even "require" is a practical equivalent to "eval", so trying to look for eval() calls and similar constructs and think you're safe doesn't work, unless you have a guarantee that the interpreter load paths will be the same when the code is run as what you think it'll be.
But in more pragmatic terms, this is a real issue because many Ruby ORMs for example will add methods that depends on the current state of the databases they connect to, so many typical Ruby applications will actually validly use method names that are not explicitly defined anywhere.