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: is dict[k] an error if k is unhashable? #65

Open
alandonovan opened this issue Jul 4, 2019 · 4 comments
Open

spec: is dict[k] an error if k is unhashable? #65

alandonovan opened this issue Jul 4, 2019 · 4 comments
Assignees

Comments

@alandonovan
Copy link
Contributor

The Go implementation of Starlark, following Python2 and 3, rejects a dictionary operation in which the key is unhashable:

$ starlark -c '{}.get([])'
Traceback (most recent call last):
  cmdline:1:7: in <toplevel>
  <builtin>: in get
Error: get: unhashable type: list

$ python2 -c '{}.get([])'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: unhashable type: 'list'

$ python3 -c '{}.get([])'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: unhashable type: 'list'

By contrast, the Java implementation permits a lookup with any value, including unhashable ones. The lookup fails, though it is not necessarily an error, so execution may continue:

$ blaze-bin/third_party/bazel/src/main/java/com/google/devtools/starlark/Starlark  
>> {}.get([])
None

(This behavior occurs even when the dict is non-empty, so it can't be explained as the implementation taking a shortcut for empty dicts.)

Clearly, the Java implementation is in fact hashing the key, so the error message ("unhashable type") issued by an update operation such as {}.update([([], 1)]) seems not to tell the whole story.

I think the spec should state that all dict operations attempt to hash the key (even when unnecessary, such as {}.get(k)) and fail if the key is unhashable.

@alandonovan alandonovan changed the title spec: is dict[key] an error if k is unhashable? spec: is dict[k] an error if k is unhashable? Jul 4, 2019
@laurentlb
Copy link
Contributor

See bazelbuild/bazel#8730

@josharian
Copy link

See also google/starlark-go#113 and google/starlark-go#165

bazel-io pushed a commit to bazelbuild/bazel that referenced this issue Jul 11, 2019
Related: bazelbuild/starlark#65, #8730

Closes #8837.

PiperOrigin-RevId: 257578468
irengrig pushed a commit to irengrig/bazel that referenced this issue Jul 15, 2019
@alandonovan
Copy link
Contributor Author

More weirdness: are functions hashable or not?

% starlark
Welcome to Starlark (go.starlark.net)
>>> {len: 1}
{<built-in function len>: 1}
>>> len in {}
False
>>> {}.get(len, False)
False

% python2
Python 2.7.17rc1 (default, Oct 10 2019, 10:26:01) 
>>> {len: 1}
{<built-in function len>: 1}
>>> len in {}
False
>>> {}.get(len, False)
False


% python3.8
Python 3.8.1 (default, Dec 31 2019, 14:30:41) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> {len: 1}
{<built-in function len>: 1}
>>> len in {}
False
>>> {}.get(len, False)
False

% blaze-bin/third_party/bazel/src/main/java/com/google/devtools/starlark/Starlark
>> {len: 1}
unhashable type: 'function'
>> len in {}
unhashable type: 'function'
>> {}.get(len, False)
unhashable type: 'function'

@brandjon
Copy link
Member

Consistency with set semantics (see also discussion in #290) also requires that we fail on unhashable values. So let's do it.

(This also suggests that a future type checker should reject attempts to access or update a dict key with unhashable type.)

Created #296 for the function question.

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

No branches or pull requests

4 participants