-
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
[Compiler-v2] Add ability check on number constraint #15346
Conversation
⏱️ 2h 58m total CI duration on this PR
|
15c8e2c
to
b9355c7
Compare
@@ -11,16 +11,11 @@ error: type `S` is missing required ability `key` (type was inferred) | |||
│ | |||
= required by instantiating type parameter `R:key` of function `both` | |||
|
|||
error: type `Coin` is missing required ability `copy` (type was inferred) | |||
┌─ tests/ability-check/v1-typing/module_call_constraints_not_satisfied.move:29:9 | |||
error: constraint `integer` does not have required ability `key` |
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 original error is shadowed by the new error.
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 you add a variant of this test that shows the original error is still there if this one is fixed?
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.
Added a test in the same file
@@ -11,6 +17,17 @@ error: type `Coin` is missing required ability `drop` (type was inferred) | |||
│ | |||
= required by instantiating type parameter `T:drop` of struct `S` | |||
|
|||
error: type `R<*error*>` is missing required ability `key` (type was inferred) |
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 a duplicated error
error: constraint `integer` does not have required ability `key` | ||
┌─ tests/ability-check/v1-typing/pack_constraint_not_satisfied.move:7:27 | ||
│ | ||
7 │ R {r:_ } = R { r: 0 }; |
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.
V1 has this error
error: constraint `integer` does not have required ability `key` | ||
┌─ tests/ability-check/v1-typing/pack_constraint_not_satisfied.move:12:44 | ||
│ | ||
12 │ R {r: R { r: _ } } = R { r: R { r: 0 }}; |
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.
V1 has this error
b9355c7
to
ea86c8d
Compare
ea86c8d
to
fd0bc1a
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.
some minor comments
@@ -459,6 +459,7 @@ impl Constraint { | |||
subs: &mut Substitution, | |||
loc: &Loc, | |||
other: &Constraint, | |||
ctx_opt: Option<ConstraintContext>, |
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.
Please add brief info to the function doc string on how this additional parameter is only used for additional error info.
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.
done
@@ -543,6 +544,32 @@ impl Constraint { | |||
*a1 = a1.union(*a2); | |||
Ok(true) | |||
}, | |||
// After the above checks on same type of contraint |
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.
// After the above checks on same type of contraint | |
// After the above checks on same type of constraint |
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.
done
@@ -543,6 +544,32 @@ impl Constraint { | |||
*a1 = a1.union(*a2); | |||
Ok(true) | |||
}, | |||
// After the above checks on same type of contraint | |||
// Check compatibility between ability and number |
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.
Are there other combinations to consider, e.g., references etc?
Could you add a comment about why this particular combination requires the special check?
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.
Added the comment
@@ -2089,7 +2089,8 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo | |||
Pattern::Struct(sid, std, variant, patterns) => { | |||
let mut new_inst = vec![]; | |||
for ty in &std.inst { | |||
let nty = subs.specialize(ty); | |||
// use `specialize_with_defaults` to get type info from constraints | |||
let nty: Type = subs.specialize_with_defaults(ty); |
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'm a bit concerned about using this here, as _with_defaults
it will turn is_integer
into u64
, though coming up with a bad test case is hard. Please add a test case to pack_constraint_not_satisfied2.move
where, instead of 0, we have a literal=MAX_U64+1?
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.
Added a new test
fd0bc1a
to
9671634
Compare
// This check is needed because sometime the concrete integer type is not available | ||
// TODO: check other combination of constraints may be necessary as well. | ||
(Constraint::HasAbilities(a1, _), Constraint::SomeNumber(_)) => { | ||
let unsupported_abilities = a1.setminus(AbilitySet::PRIMITIVES); |
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.
nit: would be nice if the common duplicate code in these two arms could be refactored out.
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 was trying to merge these two arms but could not do it because one requires mutable reference and the other one does not. Once we decide we want to generalize this check to different types of constraints, I will refactor them out.
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.
Rust doesn't allow polymorphism over mutability. :-(
} | ||
|
||
fun t0_u128() { | ||
let y = R { r: X { r: MAX_U64 + 1} }; |
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'm sorry I was unclear. Inline the number here:
let y = R { r: X { r: 18446744073709551616 } };
so we can see what happens. I would expect that the u128
type is constraining the value in that situation. But maybe a less direct situation is needed.
And now that I ask for this I suddenly realize I'm not sure what Move specifies it will do with a big constant.
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 will lead to the error
+Diagnostics:
+error: unable to infer instantiation of type `store + u128|u256` (consider providing type arguments or annotating the type)
+ ┌─ tests/bytecode-generator/bug_14629.move:14:31
+ │
+14 │ let y = R { r: X { r: 18446744073709551616 } };
+ │ ^^^^^^^^^^^^^^^^^^^^
,which I think should be fine? @brmataptos
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.
Another example:
module 0x8675309::M {
const MAX_U64: u64 = 18446744073709551615;
fun t0_u128() {
let y = R { r: X { r: MAX_U64 + 1 } };
let R { r: _r } = y;
}
In general, should the compiler infer the type as u64, which will lead to overflow? I think it should be fine as well because it can only be detected during runtime?
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.
These are both ok. I just wanted to make sure it didn't do something crazy like inferring u64
while looking for abilities and then complaining about it to the user.
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.
LGTM
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
This PR:
specialize_with_defaults
instead ofspecialize
when instantiating types for all all struct patterns in the block expression so that the default type can be inferred from constraints.key
ability and be a number. To achieve this goal, a new variantMissingAbilitiesForConstraints
is added toTypeUnificationError
.Close #14629
How Has This Been Tested?
Key Areas to Review
Whether it is OK to add the check between two different types of constraints.
Type of Change
Which Components or Systems Does This Change Impact?
Checklist