Let's say we have multiple modules(A and B) declaring the same extension on a common type (say Array) with the same function signature(say sum()). This can lead to the "Ambiguous use'" error. Even worse, if the client module also declares an extension on Array with the same function signature but a different implementation, the program will compile without any warning or error regarding the other possible candidates for the function.
Furthermore, it's not always easy to control which extensions are visible and accessible when compiling a module. Let's say Module B doesn't directly declare the extension, but it imports module B_1 that declares it. This, in turn, makes the 'sum()' function from B_1 not only visible in B but also in all modules importing B.
Use of @_implementationOnly import B_1 doesn't seem to solve the issue in this case.
One possible solution I found to prevent such namespace pollution through extensions is using the @_spi attribute. By marking the extensions with @_spi, we can hide them from clients unless they explicitly import the module with the required @_spi names.
However, I'd love to find a more systematic solution to this problem.
This is irrelevant. Type on which an extension is defined and any constraints can be anything. The extension itself can be useful for clients, but inability to limit their visibility leads to potential clashes.
to me, this looks like dialectization, over the years i’ve moved away from doing this sort of thing because it makes refactoring and sharing code between projects more difficult.
The Github issue Keith linked summarizes this long standing issue well. It's really just a compiler implementation bug, but changing the behavior would be too source breaking to consider without a language version update. Swift 6 presents an opportunity to do so, though.
I think there is an opportunity to make an additive change to the import statement now, in Swift 5. It would allow more granular filtering. Like @_spi imports, but for extensions.