Hello, I think that the error given when attempting to use a non-public member from a library is not helpful and could do with some added help to the user.
This is probably only an issue for new-ish users, and long-time Swift developers will never run into this, but it's rather confusing for learners.
Let me give an example and my thinking as I went...
I am attempting improve my knowledge about testing and SPM. I created a new package with an executable target and product (both named 'SPMTesting'). I then created a .testTarget (named 'TheTests').
In the executable's main source file I created a basic class that I could write tests for (named 'Counter'.)
I created some tests in a file ('CounterTest') for the test target and referenced the Counter class in a test.
Cannot find 'Counter' in scope
OK - I probably need to make the executable target a dependency to the Test target... I do that.
Cannot find 'Counter' in scope
Hmm, maybe I need to explicitly import
the executable module. I do that.
Cannot find 'Counter' in scope
Hmm, OK. Maybe I'm going about this all wrong, maybe you can't import
an executable - I should probably be putting these types into a Library and import that instead.
So - I make a new Library target in the package, named 'Tools' (for a lack of imagination) and define the Counter() class in there instead. Then I make that library a dependency for the executable and the test target. Also I import Tools
in both source files.
Compile:
Cannot find 'Counter' in scope
Why not? I even command-click the type name and it can take me to the definition. Why isn't it in scope?
About 15 mins later I suddenly remember about access control across files and that types and functions aren't public by default. I annotate the Counter
class with public
and it gives a different error
'Counter' initializer is inaccessible due to 'internal' protection level
Ah, a useful error message. This one gives me information that I can use to fix the issue. I add an initialiser to Counter
with a public
annotation and success - it compiles.
Perhaps most Swift devs would think "well, that's obvious, you should have known to make the types public - they default to private." But may I suggest that since (I assume) the compiler knows that the type exists, but is private, that the error is not as helpful as it could be.
Could the compiler not warn that the type exists, but is not available to the caller? Or would this be seen as a security problem, by exposing internal, private API details?
Thanks