Basically it's a scope thing.
From the documentation on our
:
An our
declaration declares an alias for a package variable that will be visible across its entire lexical scope, even across package boundaries. The package in which the variable is entered is determined at the point of the declaration, not at the point of use.
The first our
creates makes $x
an alias for $A::x
. The second one reassigns $x
to be an alias for $B::x
, shadowing/replacing the previous one so that further uses of an unqualified $x
in the same lexical scope (the file in this case since it's outside a block) refers to the B
package variable no matter what the current package is.
This duplication of names is explicitly allowed per the docs:
Multiple our
declarations with the same name in the same lexical scope are allowed if they are in different packages.