-
Notifications
You must be signed in to change notification settings - Fork 17.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
cmd/compile, runtime: initialization order within a file appears to have changed #49150
Comments
The way I read your code, and the spec, is that
cannot be initialized immediately, because the body of So my reading is that 1.17 is correct, and earlier versions are broken. Not sure what changed, though. |
isn't it the case that the body of initializeMe initializes globalX rather than depending on it? Another thing to consider is that go1.17 behaves like earlier versions if you remove the use of the indirect package, that is, the code below works as per prior versions and that it's the indirection that triggers the change in behavior. Which is likely a saving grace since if prior versions were out-of-spec then go1.17 is correct ie. go1.17 is also out of spec for the common case!
|
Not according to the spec. Initialization order only depends on lexical references. It doesn't look at, for instance, if a reference to a variable is a read or write. (Except, of course, for the assignment in the top-level declaration itself.) I'm not sure I understand your point in the latest example. |
I had misinterpreted the lexical reference (as appearing anywhere on the rhs), but, yes, the spec is quite clear, my apologies. fd22df9 - old behaviour My admittedly unclear point from the previous message is, that given the spec, wouldn't you expect my example above (without the other package) to behave the same way as the one with the indirection? My probably wrong reasoning being, for the example above:
With the other package in play.
Maybe I'm just confused! I'd be just be happy with a work around but haven't found yet. If 17.x is the correct behavior then 16 versions of the incorrect behaviour will have stored up quite a few latent bugs! |
That isn't the case here. |
I also tried it with a var, and how is Get not called on it?
|
|
ok, so just so that I understand it:
Is that the correct way to read this? Now, having taking a quick look at #43444 I can see a workaround, namely, declaring globalX before
I think you should highlight this difference in the release notes for go 1.17, it all seems pretty subtle to me. The fourth example below, I think is arguable since it currently breaks, but maybe it shouldn't.
|
Your understanding is correct. We could update the release notes. What would you want them to say? |
Anything that explains the difference between the old and new behavior with a warning to watch out for such problems and suggested work arounds. Do you want me to draft something? |
That would help. I'm not sure I exactly understand how to characterize what changed. Other than "it now better adheres to the spec". |
well, I'm similarly uncertain, but I'll draft something and you can run it by Matthew before publishing. |
can you assign the following to mdempsky to review? Please add this, or something similar, to the compiler section: go1.17 correctly implements the language specification with respect to package initialization order, earlier versions failed to do so; consequently code that depended on the previous incorrect initialization order may no longer work as expected under 1.17 and future versions. Prior versions failed to detect dependencies on declared but not initialized variables and dependencies in 'dead' code that the compiler removed before determining dependencies. A consequence of these changes is that functions called by initialization expressions that reference other initialization variables will run later than under previous versions since the initialization functions are not considered ready to be initialized until after (rather than immediately) their dependent variables are initialized. The following example illustrates the differences:
Prior to 1.17 the output would be
|
Update CI and add support for golang 1.17. As per golang/go#49150, 1.17 fixes bugs in the determination of the initialization chains in packages. Unfortunately this affected the code generated by the vdl compiler and this PR includes fixes for that. This requires that all vdl code be regenerated. Fix flaky tests.
Update CI and add support for golang 1.17. As per golang/go#49150, 1.17 fixes bugs in the determination of the initialization chains in packages. Unfortunately this affected the code generated by the vdl compiler and this PR includes fixes for that. This requires that all vdl code be regenerated. Fix flaky tests.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, with 1.17.1 and .2. It has not been a problem prior to 1.17.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Nothing new! The code that encountered the problem has been in use since 2014/15.
It is my understanding that for the code snippet below, the initializeMe function will always
be called first and before any other initialization. This has been been the case prior to
go 1.17
However, with go 1.17, this behavior appears to have changed, and
initializeMe
is no longercalled before other initialization and in my case is not called before initialization that depends
on it. I understand that there is no dependency analysis going on but there shouldn't need
since by my reading of the spec initializeMe should always be called first. I have attached
code snippets to repro the problem.
The code that seems to defeat the expected initialization involves an additional variable initialization
via an other package.
where
indirect.GetVal(d)
calls a method ond
whose implementation accesses a variable thatis initialized by
initializeMe
.What did you expect to see?
no panic.
What did you see instead?
a panic
bug.tar.gz
The text was updated successfully, but these errors were encountered: