-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add a compile error for usingnamespace crossing package boundaries #1853
Comments
Thanks for the writeup. I want to note that the existence of compile-time reflection introduces complications into the meaning of semantic versioning. For example once #1047 is implemented, or even without it, you can iterate over the member functions of a struct and emit a compile error if it is more than 10. So then presumably a library which adds a member function to a struct could be breaking code. Is that a major or a minor version bump? It can get a bit philosophical. For example, let's say that my build process creates one executable and embeds it into another one, with a maximum size of 1000 bytes. If a library updated versions and then didn't fit in 1000 bytes anymore, that could break something. But probably the machine code size is not something that is protected by the minor version bump. I agree with your problem statement in this issue. I think we need to define very carefully, exactly what constitutes a major, minor, and bugfix version bump, and explore to what extent Zig can help prove that semver is upheld (#404). |
Titus Winters has a nice talk where he discusses some of the problems with SemVer. In short, every change can be a breaking change for someone (Hyrum's law)... even bug fixes, so it is an inevitability that semver will not work as expected eventually for someone. I think This is a fundamentally a question about contracts between library authors and users. I'd argue that implictly it's the author's right to add new symbols at any time, and so while upgrading will be easiest if the user doesn't |
I suggest the 'use' documentation provide the information on these pitfalls. |
The fact that people learn to depend on features which are not part of the explicitly defined interface is not a limitation of semver. I'm with @asoffer on this one. Namespace obliteration is always a problem. Here's a simple-ish way you could solve it: If you Of course, then the compiler would need to be aware of which names are "actually" |
Please see this comment: #678 (comment) |
If you write an app like this:
then this will only compile if neither of
lib1
orlib2
export a symbol calledfoo
. If one of those libraries decides in a minor version update to export a new function calledfoo
, then it will cause a compile error in this app. Furthermore, if bothlib1
andlib2
independently decide to export a new symbolbar
in their own minor version updates, then updating those two dependencies would result in a compile error.This means one of three things:
use
is bad. (this is my choice.)As the Zig ecosystem scales up, the likelihood of this kind of symbol collision rises. If I were writing a Best Practices Guide at an organization that used Zig, I would discourage or forbid the use of
use
for this reason.Perhaps a more nuanced rule would be that
use
should never cross package boundaries. There's no semver contract between the files of a single package, so this would work around this particular issue. This is even a rule that we could enforce in the compiler, although it might backfire if people start violating the package abstraction in order to work around this restriction (likeuse @import("../../../packages/lib1/src/main.zig");
).The text was updated successfully, but these errors were encountered: