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

spec: clarify that map iteration always yields the latest version of an entry #70916

Open
prattmic opened this issue Dec 19, 2024 · 7 comments
Open
Assignees
Labels
FixPending Issues that have a fix which has not yet been reviewed or submitted. NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@prattmic
Copy link
Member

Proposal Details

Consider the following program (https://go.dev/play/p/wd1Ge2PIyAK):

package main

import "fmt"

func main() {
	m := map[string]string{
		"a": "original",
		"b": "original",
	}
	for k, v := range m {
		fmt.Println(k, v)
		m["a"] = "new"
	}
}

Map iteration order unspecified, so if "a" is produced first it will print:

a original
b original

If "b" is produced first, the spec does not specify whether this must print

b original
a new

Or if

b original
a original

is acceptable. In other words, is iteration required to produce the latest version of an entry, or is a stale version OK?

As far as I know, the gc map implementation has always produced the latest version of an entry. In fact, when implementing #54766 I fixed bugs I introduced that produced stale values under the assumption that the spec required it.

The spec does specify "If a map entry that has not yet been reached is removed during iteration, the corresponding iteration value will not be produced." In my opinion it would be odd to require deletion be tracked precisely, but not changes to values.

Thus I propose that the map portion of https://go.dev/ref/spec#For_range be amended to add "Iteration always produces the latest value of a map entry."

cc @griesemer @randall77

@gopherbot gopherbot added this to the Proposal milestone Dec 19, 2024
@ianlancetaylor ianlancetaylor moved this to Incoming in Proposals Dec 19, 2024
@zigo101
Copy link

zigo101 commented Dec 20, 2024

Same as/for slices?

@griesemer
Copy link
Contributor

griesemer commented Jan 8, 2025

I think for slices/arrays it's clearer: the produced index values i go from 0 to n-1 (for n = length), and the corresponding values are a[i] - which implies that it's always the most recent a[i].

@griesemer griesemer self-assigned this Jan 8, 2025
@griesemer
Copy link
Contributor

Not sure this needs to be a proposal.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/641555 mentions this issue: spec: clarify that map iteration always produces the latest map entries

@ianlancetaylor ianlancetaylor changed the title proposal: spec: clarify that map iteration always yields the latest version of an entry spec: clarify that map iteration always yields the latest version of an entry Jan 9, 2025
@ianlancetaylor ianlancetaylor added NeedsFix The path to resolution is known, but the work has not been done. FixPending Issues that have a fix which has not yet been reviewed or submitted. and removed Proposal labels Jan 9, 2025
@ianlancetaylor ianlancetaylor modified the milestones: Proposal, Backlog Jan 9, 2025
@griesemer
Copy link
Contributor

[From the CL discussion]

In retrospect, after starring at the spec some more, I think we don't really need this: arguably we have the same problem with slice iteration. There we say that the indices are produced from 0 to n-1, and then we say (in the table) that the corresponding value is a[i]. Slice elements act like variables (they are addressable), and in the section on variables we say "A variable's value is retrieved by referring to the variable in an expression; it is the most recent value assigned to the variable." What "most recent" means in detail is left out and for that we need the Go Memory Model.

For maps, we also say (via the table) that the (2nd) value is m[k] which should be sufficient for an implementation to behave as we'd expect. But the values of map entries don't act like variables (they are not addressable), so that phrase for variables doesn't apply. Maybe in the section on (map) index expressions we should say something like: "if the map contains an entry with key x, a[x] is the most recently stored map element with key x".

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/641856 mentions this issue: spec: add a link to Go Memory Model doc in section on variables

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FixPending Issues that have a fix which has not yet been reviewed or submitted. NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants