Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Update to pass test for unhashable collections#4640

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
youknowone merged 11 commits intoRustPython:mainfromseungha-kim:feature/unhashable
Mar 7, 2023

Conversation

seungha-kim
Copy link
Contributor

In CPython:

  • If a type is marked as unhashable on the native side (i.e.PyObject_HashNotImplemented is assigned to hash slot), then__hash__ attribute of the type dict is set to None so that the type is considered as unhashable on Python side too.
  • If a type is created at runtime and"__hash__": None is given as the type dict (liketype('C', (object,), {'__hash__': None})), then the hash slot is filled with PyObject_HashNotImplemented.

In RustPython, Unhashable trait exists to mark a type as unhashble. But there is no way to check if a type implements Unhashable trait at runtime, so it is hard to follow the CPython's mechanism.

So I've addedunhashable_wrapper function similar to PyObject_HashNotImplemented, and used that as a marker for unhashable on the native side.


Thanks for the advice from@youknowone !

youknowone reacted with thumbs up emojiyouknowone reacted with hooray emoji
Comment on lines 605 to 610
context
.types
.list_type
.slots
.hash
.store(Some(unhashable_wrapper));
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Maybe there is a more elegant way to do this...?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

And I missed adding unhashable_wrapper thing for deque, so test_deque fails. Deque implementation resides in collections.rs, but there is no type initialization function similar to thisinit function incollections.rs. Where is a good place to put this code?

@youknowone
Copy link
Member

I will look in the details.
The single failing test is this one:

======================================================================FAIL: test_hash (test.test_deque.TestBasic.test_hash)----------------------------------------------------------------------Traceback (most recent call last):  File "/home/runner/work/RustPython/RustPython/pylib/Lib/test/test_deque.py", line 537, in test_hash    self.assertRaises(TypeError, hash, deque('abc'))AssertionError: TypeError not raised by hash

Comment on lines 94 to 99
context
.types
.bytearray_type
.slots
.hash
.store(Some(unhashable_wrapper));
Copy link
Member

@youknowoneyouknowoneMar 5, 2023
edited
Loading

Choose a reason for hiding this comment

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

I have a suggestion about the location of this initialization.

We put these information toPyClassDef for builtin types.
addingHASHABLE const with default value false will be good.

Then we use the information during making class. that'sPyClassImpl::make_slots.

seungha-kim reacted with thumbs up emoji
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I'll try.

Copy link
Member

Choose a reason for hiding this comment

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

maybe default value is false, not true. hashable is common in builtin type world, but not outside.

Copy link
Member

@youknowoneyouknowone left a comment

Choose a reason for hiding this comment

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

I added a few more style suggestions.

Comment on lines 120 to 121
.map(|h| h as usize == unhashable_wrapper as usize)
.unwrap_or(false)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.map(|h| hasusize == unhashable_wrapperasusize)
.unwrap_or(false)
.map_or(0, |h| hasusize) == unhashable_wrapperasusize

the cost ofmap_or(0, |h| h as usize) is zero here due to its layout.

@@ -112,6 +112,16 @@ pub trait PyClassImpl: PyClassDef {
.into();
class.set_attr(identifier!(ctx, __new__), bound);
}

if class
Copy link
Member

Choose a reason for hiding this comment

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

I'd like to check if this is related to#3460 later

seungha-kim reacted with thumbs up emoji
Comment on lines 426 to 427
.map(|a| a.is(&ctx.none()))
.unwrap_or(false);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.map(|a| a.is(&ctx.none()))
.unwrap_or(false);
.map_or(false, |a| a.is(&ctx.none));

ctx.none() increase reference count ofNone. We don't need to do.

Comment on lines 428 to 432
if is_unhashable {
toggle_slot!(hash, unhashable_wrapper);
} else {
toggle_slot!(hash, hash_wrapper);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if is_unhashable{
toggle_slot!(hash, unhashable_wrapper);
}else{
toggle_slot!(hash, hash_wrapper);
}
let wrapper =if is_unhashable{
unhashable_wrapper
}else{
hash_wrapper
};
toggle_slot!(wrapper)

@@ -243,6 +243,11 @@ fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
}
}

/// Marks a type as unhashable. Similar to PyObject_HashNotImplemented in CPython
pub fn unhashable_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pubfnunhashable_wrapper(zelf:&PyObject,vm:&VirtualMachine) ->PyResult<PyHash>{
pubfnhash_unhashable(zelf:&PyObject,vm:&VirtualMachine) ->PyResult<PyHash>{

Other functions are called wrapper because they are wrapping a python call.
This function is not a wrapper of python call, so giving a different name would be better.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, probablyhash_not_implemented by following cpython naming

Copy link
Member

@youknowoneyouknowone left a comment

Choose a reason for hiding this comment

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

Great! it now passes deque too.

@@ -60,6 +60,7 @@ pub trait PyClassDef {
const TP_NAME: &'static str;
const DOC: Option<&'static str> = None;
const BASICSIZE: usize;
const UNHASHABLE: bool;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
constUNHASHABLE:bool;
constUNHASHABLE:bool =false;

default value can be placed here

@@ -71,6 +72,7 @@ where
const TP_NAME: &'static str = T::TP_NAME;
const DOC: Option<&'static str> = T::DOC;
const BASICSIZE: usize = T::BASICSIZE;
const UNHASHABLE: bool = false;
Copy link
Member

Choose a reason for hiding this comment

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

PyRef<T> must followsT

Suggested change
constUNHASHABLE:bool =false;
constUNHASHABLE:bool =T::UNHASHABLE;

@youknowoneyouknowone added the z-ls-2023Tag to track Line OSS Sprint 2023 labelMar 7, 2023
Copy link
Member

@youknowoneyouknowone left a comment

Choose a reason for hiding this comment

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

Looks great, thank you for digging in this tricky issue.

seungha-kim reacted with laugh emoji
@youknowoneyouknowone merged commit223fe14 intoRustPython:mainMar 7, 2023
@seungha-kimseungha-kim deleted the feature/unhashable branchMarch 7, 2023 14:53
minhrongcon2000 pushed a commit to minhrongcon2000/RustPython that referenced this pull requestMar 10, 2023
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@youknowoneyouknowoneyouknowone approved these changes

Assignees
No one assigned
Labels
z-ls-2023Tag to track Line OSS Sprint 2023
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@seungha-kim@youknowone@blue-pandaa

[8]ページ先頭

©2009-2025 Movatter.jp