Skip to content
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

proposal: spec: do not specify initialization order of package-level variables w/o dependencies #8715

Closed
griesemer opened this issue Sep 12, 2014 · 4 comments
Labels
FrozenDueToAge LanguageChange v2 A language change or incompatible library change
Milestone

Comments

@griesemer
Copy link
Contributor

Gordon Klaus (gordon.klaus@gmail.com) made a (in my mind) intriguing suggestion: He
proposes that initialization order should not be further specified beyond the existing
dependencies (and thus not depend on declaration order).

I would add to this that init() functions, too, should be invoked in unspecified order.

I very much like this idea for several reasons:

1) At the package-level, excluding variable initialization, declaration order is
irrelevant for the meaning of a program (note that iota is an explicit constant).

2) Across files of a package, the initialization order of independent variables depends
on the order in which the files are presented to the compiler. In practice, a programmer
doesn't have control over that order when using go build. It may be in filename order,
but it could be random (the files might be stored in a set). Thus, this is a situation
where the semantics of a package is not expressed in the source per se, but in how the
source code is handled by tools. This seems a bad idea.

3) The two compilers (currently, 9/12/2014) disagree in some cases about the correct
initialization order.

4) It would simplify the spec.

5) Where initialization order matters, a specific initialization function is the
preferred way of expressing that dependency.

6) Reordering code may subtly brake implicit ordering dependencies.

In order for such an approach to work well (and expose errors), an implementation should
enforce a different initialization order (while respecting dependencies) for each run,
like we have enforced different map iteration orders for each map iteration.

Here's a possible implementation:

1) Package-level variables that have no initialization expression, or have an
initialization expression that is independent on any other variable and has no
observable side-effects (incl. panics), are initialized in whatever order is easiest and
most efficient to generate code for, if code is even necessary.

2) For each of the remaining (usually small number of) variables x, allocate a
zero-initialized boolean flag bx and generate an accessor function fx as follows:

func fx() typeof(x) {
    if !bx {
        x = // init expression of x
        bx = true
    }
    return x
}

3) In all init expressions, replace any reference to variables with calls to the
corresponding accessor functions, if any.

4) Add all the functions fx together with all init functions to a map.

5) Iterate through the map (in random order) and invoke each function.

That is, we solve the dependency problem at run-time for each package, and each time it
is as if the variables were declared in a different order.

The extra code would be fairly small given the small number of variables that are
initialized with dependencies or side-effects. The necessary program transformations are
straight-forward in a compiler.
@griesemer
Copy link
Contributor Author

Comment 1:

Labels changed: added go2.

Status changed to LongTerm.

@griesemer griesemer added longterm LanguageChange v2 A language change or incompatible library change labels Sep 12, 2014
@griesemer griesemer self-assigned this Sep 12, 2014
@rsc rsc added this to the Unplanned milestone Apr 10, 2015
@dmitshur
Copy link
Contributor

dmitshur commented Jun 2, 2015

I very much like this idea also. 👍 Primarily because it attains additional simplicity.

@rsc
Copy link
Contributor

rsc commented Jun 16, 2017

An old issue and not until Go 2 anyway, but I think it would be a mistake to relax these rules. Much like leaving map iteration order unspecified led to implementation-dependent code that only worked with one map iteration order, relaxing the init order here will lead to the same kind of code that only works with certain Go implementations. If there's any wiggle room left, I'd argue we should make things completely specified, not move in the other direction.

@rsc rsc changed the title spec: do not specify initialization order of package-level variables w/o dependencies proposal: spec: do not specify initialization order of package-level variables w/o dependencies Jun 17, 2017
@griesemer
Copy link
Contributor Author

Over the last few years we decided for making the spec more deterministic, not less so (with the notable exception of map iteration order). Proposal withdrawn.

@golang golang locked and limited conversation to collaborators Jan 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

5 participants