-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
[move] Implement generic comparison method in move cmp::compare #14714
Conversation
⏱️ 1h 45m total CI duration on this PR
🚨 1 job on the last run was significantly faster/slower than expected
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## igor/enable_move_2_for_framework #14714 +/- ##
===================================================================
Coverage ? 57.4%
===================================================================
Files ? 859
Lines ? 211663
Branches ? 0
===================================================================
Hits ? 121527
Misses ? 90136
Partials ? 0 ☔ View full report in Codecov by Sentry. |
/// 2 iff first value is larger than the second | ||
native fun compare_impl<T>(first: &T, second: &T): u8; | ||
|
||
struct Ordering has copy, drop { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use enum for this now? cc @wrwg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would enum be better here? Would enums be more inefficient here?
how would the native function return an enum that is defined in the module here?
} | ||
|
||
// #[test] | ||
// fun test_compare_enums() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is enum ignored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum's are not yet enabled in the framework.
} | ||
|
||
let len_cmp = l.len().cmp(&r.len()); | ||
if len_cmp.is_ne() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just l.len().cmp(&r.len())
(VecBool(r1), VecBool(r2)) => r1.borrow()[self.idx].cmp(&r2.borrow()[other.idx]), | ||
(VecAddress(r1), VecAddress(r2)) => r1.borrow()[self.idx].cmp(&r2.borrow()[other.idx]), | ||
|
||
// Equality between a generic and a specialized container. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not equality
| (IndexedRef(_), _) | ||
| (DelayedFieldID { .. }, _) => { | ||
return Err(PartialVMError::new(StatusCode::INTERNAL_TYPE_ERROR) | ||
.with_message(format!("cannot compare values: {:?}, {:?}", self, other))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we use Display
instead of Debug
in the message (hopefully that means more stable error message)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is copied from equals. I am not sure what is more stable from MoveVM prespective, but seems like this should be the same as in equals.
and changing equals would require feature flag? if we wanted to change eeverything to {} , we should do that separately, I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay.. putting Debug text to messages we dare not to change generally makes me very sad but you don't make it worse I guess
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vgao1996 for thoughts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message of VMError is (more or less unfortunately, making it hard to show to users) not stored on chain, so I do not think it is very important to be stable.
| (VecAddress(_), _) => { | ||
return Err( | ||
PartialVMError::new(StatusCode::INTERNAL_TYPE_ERROR).with_message(format!( | ||
"cannot compare container values: {:?}, {:?}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
@@ -36,5 +39,8 @@ crate::gas_schedule::macros::define_gas_parameters!( | |||
[bcs_serialized_size_base: InternalGas, { RELEASE_V1_18.. => "bcs.serialized_size.base" }, 735], | |||
[bcs_serialized_size_per_byte_serialized: InternalGasPerByte, { RELEASE_V1_18.. => "bcs.serialized_size.per_byte_serialized" }, 36], | |||
[bcs_serialized_size_failure: InternalGas, { RELEASE_V1_18.. => "bcs.serialized_size.failure" }, 3676], | |||
|
|||
[cmp_compare_base: InternalGas, { RELEASE_V1_21.. => "cmp.base" }, 367], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do we get 367?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copied from equality costs
const EQUAL: u8 = 1; | ||
const LESS_THAN: u8 = 0; | ||
const GREATER_THAN: u8 = 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not enum?
struct Ordering has copy, drop { | ||
value: u8, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
less_than, equal, greater_than can be ordering and return value. Why do we choose u8 instead?
a2a930b
to
b024117
Compare
I cannot use move 2 features (i.e. enums), until framework is compiled with it. I can modify it in additional commit in the stack, and decide when landing. |
0df908c
to
0fab436
Compare
b024117
to
b508022
Compare
0fab436
to
b1a2e70
Compare
b508022
to
18ba714
Compare
b1a2e70
to
6b493cd
Compare
18ba714
to
b0d9226
Compare
6b493cd
to
6046016
Compare
cef8611
to
df51e9c
Compare
5394fb5
to
927268c
Compare
fn compare(&self, other: &Self) -> PartialVMResult<Ordering> { | ||
use Container::*; | ||
|
||
let res = match ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was wondering if the logic would be easier if you do a read_ref on both ends and compare?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure, why equals doesn't do that? maybe perf?
(Bool(l), Bool(r)) => l.cmp(r), | ||
(Address(l), Address(r)) => l.cmp(r), | ||
|
||
(Container(l), Container(r)) => l.compare(r)?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a Container
be compared with IndexedRef
etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, as equals doesn't have those either.
The value logic is indeed very redundent. Let's try to blow that logic as soon as possible... @ziaptos |
@runtian-zhou do you mean 100% code coverage with move unit tests, or something else? For the complexity of code - code (i.e. all the matches) have been copied 1-1 from equals, so they should cover all the cases exactly. signature of this move function uses enums, so I cannot land the move file with private function, until move 2 is enabled for the framework. So I've separated them out - but will confirm all tests in #15245 pass, before I land this one. |
9e0fd82
to
db496b3
Compare
37384ce
to
6bd7875
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed this before, but didn't stamp
db496b3
to
43449cb
Compare
7f9c9c7
to
c721045
Compare
c721045
to
3144f47
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
3144f47
to
73c4d4d
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ Forge suite
|
✅ Forge suite
|
✅ Forge suite
|
Description
Implement generic comparison operator for any move type.
This enables writing generic methods that require comparison - for example binary_search on a vector.
Since move doesn't have signed integers, comparison return value is not intuitive (increased by 1 from usual -1, 0, 1), and so is wrapped into Ordering struct - so users don't need to think about it (with move 2, calling those will be pretty intuitive)
Type of Change
Which Components or Systems Does This Change Impact?
How Has This Been Tested?
Provided unit tests
Key Areas to Review
Checklist