Skip to content

starlark: use Unhashable errors to indicate hash failures#165

Open
josharian wants to merge 1 commit into
google:masterfrom
josharian:unhashable
Open

starlark: use Unhashable errors to indicate hash failures#165
josharian wants to merge 1 commit into
google:masterfrom
josharian:unhashable

Conversation

@josharian
Copy link
Copy Markdown
Collaborator

Fixes #113. See that issue for discussion.

Copy link
Copy Markdown
Contributor

@alandonovan alandonovan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, recently in another thread we were discussing whether to allow objects of mutable types (such as dict and especially list) to become hashable once frozen. The Java implementation has always allowed this (and thus Bazel depends on it), but the Go impl, following Python, does not. The main argument in favor is that unlike in Python users cannot define their own classes and hash/eq relations so we need to allow simple structs to be used as dict keys even if they contain (frozen) lists. The main argument against is that it is non-monotonic (freezing an object takes away some operations but adds others), and that it is tricky to implement robustly because mutable objects may contain cycles (e.g. a list that contains itself).

I don't think a decision has been reached, but the implementation of that feature would require significant changes to the existing Hash method to make it resemble EqualDepth (with a depth bound) or writeValue (with a cycle check). Either way, we would need a new Hash method with an extra parameter exposed in the API. We could also piggyback a change of type of the hash from uint32 to uint, and perhaps add a seed value into the hasher. The old Value.Hash method would be deprecated as we migrate to a new optional Hashable interface.

Comment thread starlark/value.go
}

// An Unhashable error indicates that a call to Hash has failed because the Value is not hashable.
type Unhashable string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnhashableError

Comment thread starlark/value.go
func (si stringIterable) Freeze() {} // immutable
func (si stringIterable) Truth() Bool { return True }
func (si stringIterable) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", si.Type()) }
func (si stringIterable) Hash() (uint32, error) { return 0, Unhashable("unhashable: " + si.Type()) }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper function?

func unhashable(x Value) (uint, error) {
return 0, Unhashable(fmt.Sprintf("unhashable: " + x.Type())
}

@josharian
Copy link
Copy Markdown
Collaborator Author

I don't think a decision has been reached, but the implementation of that feature would require significant changes to the existing Hash method

Ack. Shall we put this PR on hold until a decision has been reached?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants