Yes, because an impl is a static property of the code, considered at compile time regardless of what will execute. This is not like Python or any other dynamic language that can modify types at runtime.
For one, you can define items within function scope, like a nested fn, const, or even a new type. These are "global" more in the static sense, that their existence is not dependent on the runtime conditions of the function you define them in. From outside the function, there's no way to name the items within, so they're effectively scoped private regardless of whether they have pub.
Given that you can define types within a function, it also makes sense that you can impl those types. Coherence allows you to write such impls anywhere in the crate, as long as you can name it. Since you can only reach a fn's items from within, the impl has to go there too.
Since you need to be able to impl types within, there's just not much reason to limit you from also writing an impl for things from outer scopes. I mean, I'd probably frown on that in a code review, but the compiler doesn't need to have an opinion on it.