Undecidability of telling if a program returns true or false
Assume you have a function like the one you described:

def haltify(f):
    # Never fails to halt.
    # If 'f' halts, returns f().
    # If 'f' doesn't halt, anything could be returned.
    ... magic ...


But then someone comes along and does this:

def evil():
    return not haltify(evil)


See the problem?


If haltify(f) is guaranteed to halt for all f, then evil is also guaranteed to halt because it just calls haltify on a specific f and inverts the output.
Since evil halts, haltify(evil) must evaluate to the same thing as evil().
So not haltify(evil) simplifies to not evil() and that's what evil() returns.
That's a problem, because there's no x satisfying x == not x. Evil's result is contradictory.
Therefore one of the assumptions we used is wrong: either haltify isn't guaranteed to halt, or it isn't guaranteed to return f() when passed a halting f.


Bonus exercise: why doesn't the function def good(): return haltify(good) cause problems for haltify, despite apparently simplifying to the infinite loop def good(): return good()?