Conversation
The exponentiation shortcut returned the base unchanged for 0 and 1 without looking at the sign of the exponent, so 0 ** (-1) evaluated to 0 instead of failing as a division by zero. Return nullopt for that case, the same way the division and modulo cases do for a zero divisor. Fixes argotorg#16982.
|
Can you please rebase this on top of |
|
The text you put into this description doesn't focus on the change. Please fix it to laser-focus on the changeset in this PR. |
msooseth
left a comment
There was a problem hiding this comment.
- Fix description.
- Explain rationale.
- Fix comment
Thanks!
|
|
||
| // x ** 0 = 1 | ||
| // for 0, 1 and -1 the size of the exponent doesn't have to be restricted | ||
| // 0 ** -n = 1 / 0 is a division by zero |
There was a problem hiding this comment.
This goes to the if line below.
There was a problem hiding this comment.
It seems that this is a fix for #16982? @msooseth is right - the description is gibberish and must be fixed. It's also ignoring out template and missing the AI disclaimer.
It also looks like the the PR patches only a single symptom instead of addressing the bug thoroughly - the scientific form of literals seems to also be affected (0e-1 evaluates to zero as well, even after this fix).
This is actually a good example of why trying to patch random bugs en masse is often more of a burden than help for us. A critical look at the problem is just as important as the fix itself. We'd rather have one good, complete contribution than multiple PRs that just scratch the surface.
I'm going to close the PR as the issue is not yet ready to be worked on. The example I found indicates that the scope is larger than originally reported and the helpful thing at this stage is to explore that in the issue rather than post code that has to be reviewed. You also have multiple other pending PRs (#17010, #16949) that need to be reviewed first.
There was a problem hiding this comment.
A syntax test does not verify that the result is correct. We should have a semantic test for this.
| uint constant a = 0 ** (-1); | ||
| uint constant b = 0 ** (-2); | ||
| function f() public pure returns (uint) { | ||
| return 0 ** (-1); | ||
| } |
There was a problem hiding this comment.
constant is superfluous. The effect would be the same with a normal state variable. If your intention was to guarantee that this is comptime evaluated, you should put it in a layout specifier or array size instead.
There was a problem hiding this comment.
The name of this test is misleading and does not really describe what it does. It's not testing only operations with zero base. Seems to be covering negative/positive exponent/base combinations. Though for that it would also cover some values that are not 0 or 1 in each case.
| @@ -0,0 +1,11 @@ | |||
| contract C { | |||
| uint constant a = 0 ** (-1); | |||
There was a problem hiding this comment.
Please check if we have tests for scientific form as well. I.e. 0e-1. If we don't we should add them.
There was a problem hiding this comment.
Also constants. But not the way you're using them - constants that are used within the expression, i.e.:
uint constant SIZE = ZERO ** MINUS_ONE;uint array[ZERO ** MINUS_ONE];uint array[SIZE];
The first one should compile and revert at runtime. The second and third should fail at compilation time.
| uint constant c = 1 ** (-1); | ||
| int constant d = (-1) ** (-1); |
There was a problem hiding this comment.
No need to parenthesize if it's not a complex expression.
| uint constant c = 1 ** (-1); | |
| int constant d = (-1) ** (-1); | |
| uint constant c = 1**-1; | |
| int constant d = (-1)**-1; |
| Compiler Features: | ||
|
|
||
| Bugfixes: | ||
| * Type Checker: Reject `0 ** (-1)` and other literal expressions with base `0` and a negative exponent as a division by zero instead of silently evaluating them to `0`. |
There was a problem hiding this comment.
| * Type Checker: Reject `0 ** (-1)` and other literal expressions with base `0` and a negative exponent as a division by zero instead of silently evaluating them to `0`. | |
| * Constant Evaluator: Reject exponentiation with base `0` and a negative exponent in comptime expressions as a division by zero instead of evaluating it to `0`. |
The path in
non_membershipwas walked fromindex, which nothing tied toqueried_key, andcalculate_rootskipped zero siblings, so a sibling's slot was not tied to a level either. The two new pedersen tests are the forgeries from #72 and both passed on main: key 1's siblings moved to slots where key 3's bits give the same left/right order, and key 1's honest path walked with key 3 as the queried key. Each proves key 3 absent from a tree that holds it.Every level from the deepest sibling up to the root is now hashed, zero siblings included, which is what the zk-kit JS tree does (its add pushes a zero sibling per shared bit and hashes it), so a slot is a level and every path bit above the matching entry is read. That alone rejects the relocation. The index is then bound with
T: From<Field>, which Field and the noir-bignum types already implement, so no signatures change and the bignum test still passes. The new poseidon2 fixtures were generated with@zk-kit/smtand a leaf marker of 0, and that setup reproduces the existing roots too. A 254-level Poseidon2 non-membership goes from 4071 to 4372 ACIR opcodes.Fixes #72