Confused About Shadowing of Functions From Another Module

So, my intuition of shadowing of functions is that the compiler will prefer the version from my module unless the arguments don't match, but if I shadow print like so:

import func Foundation.puts

private extension StaticString {
    @_transparent
    var cString: UnsafePointer<CChar> {
        UnsafeRawPointer(utf8Start)
            .assumingMemoryBound(to: CChar.self)
    }
}

func print(_ string: StaticString) {
    puts(string.cString)
}

// Calls Swift.print, and does a surprisingly large amount of work to print
// something that should constant propagate to a zstring and a count.
print("Hello, world!")

It calls Swift.print instead of my version that delegates to puts. That would make me think that maybe the compiler just prefers String to StaticString, except that if I wrap the definition and call of print into a smaller scope, then my version is the one that's called.

do {
    func print(_ string: StaticString) {
        puts(string.cString)
    }

    // Calls my print and constant propagates "Hello world!" into a zstring
    print("Hello, world!")
}

So, in short, I have no idea how the compiler decides which version of a shadowed function to use.

1 Like