A finally block runs before the return value is used

The return expression is evaluated before finally executes, but the value is not handed to the caller until afterwards — which means a finally that returns wins, silently.

function f(): int
{
    try {
        return 1;
    } finally {
        return 2;      // wins. and swallows an exception too.
    }
}

f();   // 2

// what finally is for:
try {
    $lock->acquire();
    return $this->work();
} finally {
    $lock->release();
}

A return inside finally discards both the original return value and any exception in flight, which turns a crash into a silently wrong result. Some static analysers flag it and most coding standards forbid it, for good reason. The legitimate use is exactly the second example — releasing something on every path out, including the ones nobody anticipated — and keeping the block to cleanup only is what makes it predictable.