-
-
Notifications
You must be signed in to change notification settings - Fork 810
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
Force return statement check #590
Comments
As I think @yzhang90 has noted, this is actually subtletly very hard (but I'd argue still necessary) because of blocks, for example the following would pass your check but still fail to return anything: def Foo(a: bool) -> num:
if a:
return 1 |
I think we could track each path and make sure each one has a return. That being said, a good first step would be to check for the existence of any |
Agreed. And I think currently viper programs will probably be simple enough that most |
Actually it's probably much simpler than that, we have a checker that check correct return statements by type. And we just then need to make sure each function has at minimum one return. All those in the ifs will be handled by the return type checker, ie. Not None. ;) |
I will tackle this one next, it's just building a map of functions that have return and erroring if any are missing (my gut feel says just populating a map in parse_return) , will show you :) |
@jacqueswww How does your proposal deal with this: def foo(a: bool) -> num:
if a:
return 1 |
Ah I see, now. I have a few ideas. Looking forward to challenge ;) |
or this (this should pass): def foo(a: bool) -> num:
b: num = 0
if a:
b = 1
else:
return 0
return b |
It shouldn't be too hard, my point is it is a harder algorithm because you have to explore |
And also the result if no return is taken in some subset of branches (and deferred to the end) |
P.S. I think this is actually a formal verification problem lol |
Yes you are right, one will have to figure out a way for the branches to take the default else into account, hmmm let me research it some more. 😂 |
Yeah, I think there are standard FV algorithms for doing this, I think it usually involves holding an additional bookkeping variables while you're parsing a given function, then testing those instead. |
@fubuloubu @DavidKnott consider this rule set: 1.) There must be at least one The problem with a nested return comes in that all paths have to be considered as you mentioned, however if we force the rule of a default return statement. Are we perhaps gaining clarity in the program ? And thereby simplifying this check. I personally always read default returns better than nested ones: def a() -> num:
if ...:
return 1
else:
return 2 Is more difficult for me to read than: def a() -> num:
if ...:
return 1
return 2 Maybe I am the exception ;) But the one thing we can agree on to implement so long, is the check for rule 1. I will proceed with the partial PR so long that does that check. |
1 is a good start and get's us halfway there, I think that is okay to add. 2 requires that much more advanced check, and since checking for a default return is a special case of the general problem of branched returns, I don't think we want to arbitrarily disallow a certain type of style as a first step, so I think we need to leave 2 to when both parts of the check can be performed. Which means really just the general case check of branched returns, since default return is simply a special case. 2 will override 1 when it is complete. |
@fubuloubu @jacqueswww Let me first start with an example(just some pseudo code):
This is valid in case With this in mind, let me describe the algorithm:
You just need to call |
@yzhang90 The idea would be adding a |
@DavidKnott I'm not sure I fully got your questions. What we propose here is an simple algorithm to conservatively check whether a function has return statement on all possible path. If the |
@DavidKnott Kind of. You can say that an end return statement is a special case of this algorithm, and given it's existence you can just skip the check because the answer is trivial. The |
The following program should be rejected:
People should instead write:
Though the second |
Summarize: REJECT for i in list:
if i == n:
return i ACCEPT for i in list:
if i == n:
return i
return 0 # Accept because "End return statement" exists REJECT for i in list:
if i == n:
return i
if n > len(list):
return 0 |
So slight modification to their algorithm: def check_return(statements):
if statements[-1] is 'return' and statements[-1] is at base indentation:
return True # Trivial case, probably 60% of all cases
for st in statements:
if(st is 'return'):
return True
if(statement is 'if then_stmts else else_stmts'):
then_br_return = check_return(then_stmts)
else_br_return = check_return(else_stmts)
if(then_br_return and else_br_return):
return True
return False |
* Added get_logs method to return a list of logs with optional filtering; changed get_log fixture to use last entry in get_logs list for specific log name * WIP overhaul of types * Draft of viper-by-example. * fixes voting with delegation example * use falsey-ness of 0x0000000000000000000000000000000000000000 * use falsey-ness of 0x0000000000000000000000000000000000000000 (reverted from commit 21cc53a) * use falsey-ness of 0x0000000000000000000000000000000000000000 * iff --> if and only if * Adds basic for loop for in memory list. * Adds test for literal list. * Adds for i in list support from storage and list literals. * Adds support for i in list of other BaseTypes. * Add StructureException testcase for iterating over a nested list. * Allow skip of the event name * Change function to func * Changed get_log() to get_last_log(), removed optional log name from usages * Make corrections according to suggestions. * Minor typo. * Adds basic bytes as map keys support. * Adds support for mapping literal bytes. * fix the problems when install viper in Ubuntu16.04 * Adds test for long than 32 bytes keys. * Adds test for mismatched bytes size map assign. * Adds variable name to i_pos, so it doesn't conflict. * Adds exceptions for altering lists whilst iterating them. * Fixe for altering list in iteration exception check. * Adds tests for assert x in list * Added reference types. * Add the packaging metadata to build the viper snap * Improves ownership test - to be more realistic. * Modified assert_tx_failed() to remove reference to tester as tester reference inside setup_transaction_tests.py was referencing the same module * Add 65 and 25 gas to CLAMP and ASSERT pseudo opcodes, based on test_decimals.py * Various changes to gas estimation. - Fixes with statement estimation to total all underlying args. - Adds add_gas parameter to LLLNode to allow more advanced gas calculations to be assigned to an LLLNode, see make_byte_array_copier as an example. * Replace get_contract with get_contract_with_gas_estimation. * Adds test for keys with a very long byte length. * Removed compound calling, small touchups * Minor spelling fix * Remove empty test * Refactor code parsing * Fix typo in folder name * Make pseudo opcode gas estimate a single value. * Add test for colored gas estimate output when using -f ir. * Remove tester from assert_tx_failed. * Move test_company file into proper folder * Fix constant clamp checks / change constant clamp checks to compile time * Add fixture to directly test LLL * Add clamp tests at the LLL level * Break out `test_parser.py` into test specific files * Change to assert_tx_failed * Add staticcall opcode for constant function calls * Test constant external function calls * Remove repetitive assert_tx_failed * Create Viper VIP template * Add link to VIP template to the issue template * Improve rlp decoding gas estimation * Add VIP link to contributing docs * fix issue vyperlang#453 * use clamp constants for literals as well * fix num_min_literal parsing failure * fix test coverage * fix issue vyperlang#448: compile_lll.py: buggy translation of LLL operator `sha3_32` * add sha3_32 compilation test * Add checks preventing assigning values on defining types. * Fix gas estimation error * Fix repeat LLL with <= 0 iteration * Add test for repat lll * Add depth check to with "set" statement * Require function visibility declaration * Add tests for public decorator * Add public decorator to tests (vyperlang#474) * Document function visibility requirements * Clarifies expectation in error message This would have helped me when I saw this error learning Viper for the first time. * Note internal or public decorator requirement * Fixes test with for function visibility. * Add the install instructions for the Viper snap This requries vyperlang#445, and enabling the continuous delivery on https://build.snapcraft.io * Allow for gas estimation tests for constants * Add gas estimation for create_with_code_of * ad logs to company.v.py with tests * document event in structure of a contract * move events before global declarations * remove unused import * types.py: Remove duplicated method Fix vyperlang#488 * Adds support -f bytecode_runtime. * cleans up test_logs * Use revert opcode for assert statements * Show lineno of base_type_conversion error Fix vyperlang#498 * Show lineno of undeclared function visibility Fix vyperlang#489 * Adds basic test for bytecode_runtime generation. * add clamp_nonzero to modulo arithemetic * Add modulo tests and refactor simple auction example * Use `with` to decrease repetition * Change vipercoin from returning false to throwing * Add check to as_num256 to make sure number is greater than 0 * Improve contributing .rst - Fixes a link that wasn't displaying correctly. - Makes some instructions more concise. - Changes old `:ref:building-from-source`, to link to installation instructions. * Added testing and deployment doc * Fix augassignment checks * Test for in list invalids * Remove repetitive error and fix typo * Begin adding built in erc20 external call functionality * Add implied erc20 token abi fucntionality * Add on chain market maker example * Test implied erc20 abi functionality * Update on chain market maker and erc20 abi * Change @internal decorator to @Private decorator. * Add support for logging a variable of list type. * Adds tests for logging of list types. * Fix for log packing on list variable. * Add error if log has wrong number of arguments * Add log test and improve bytes as input * Improve variable naming / fix bytes as input * Clean up tests * Adds Fix vyperlang#531. Check return type of lists match. * Adds more tests for logging of lists. * Adds Fix vyperlang#504 for clamping decimal literals correctly. * Use revert for clamps * Fix exponents with units * Create a contract data type * Remove .python-version, update .gitignore * Improve vipercoin example: link out to resources describing attack vectors * Test the contract data type * Update version of ethereum * Improves gas estimate on internal call. * Removed suicide keyword * Carry over add_gas_estimate in optimizer. * Adds gas estimation for internal calls. * Added test for invalid keyword * not official a language > officially * Changing notes to be indented blocks starting on the line after .. note:: https://sublime-and-sphinx-guide.readthedocs.io/en/latest/notes_warnings.html * Adds storage list logging support. * Adds test to check list logging is of correct (sub)type. * Splitting comments over two lines where necessary to fit on the page on readthedocs * Update to use conftest; fix some incorrect tests * Update Safe Remote Purchases: line numbers, minor edits * Updates from code review * Add modulo math checks * Adds support for logging bytes from storage. * Adds exception to limit to 32 bytes of bytes type logging (restriction for the time being). * virtualenv -p /usr/local/lib/python3.6/bin/python3 > virtualenv -p python3.6 Related: vyperlang#558 * Add a note on how to fix `fatal error: openssl/aes.h: No such file or directory` in the `make` output * removed extraneous backtick ` * Minor edits with ``num`` type > with the ``num`` type crowdfunding period is over - as determined> crowdfunding period is over—as determined * Minor edits voting add a comma > to vote, and each add a comma > to vote, or * Improve for loop error * Adds test for logging a decimal list. * :ref:`function-calls` > :ref:`Function-calls` * Minor edits types.rst * Add length check to event topics * Fix and test logging with units * Improve type parsing error message * Add valid call keyword list to utils * Add length check to event topics * Partial fix for vyperlang#590. Adds check for a minimum of one return statement. * Fixes test that were missing return statements. * Adds example of return checker behaving incorrectly. * Update dockerfile to use slim image base * Remove commented out directives * Reduce num256_add gas cost * Tag built image as viper * Add built-in function docs * Fix on chain market maker * Add comments to on chain market maker * Change badges from viper to vyper
* Change to assert_tx_failed * Add staticcall opcode for constant function calls * Test constant external function calls * Remove repetitive assert_tx_failed * Create Viper VIP template * Add link to VIP template to the issue template * Improve rlp decoding gas estimation * Add VIP link to contributing docs * fix issue vyperlang#453 * use clamp constants for literals as well * fix num_min_literal parsing failure * fix test coverage * fix issue vyperlang#448: compile_lll.py: buggy translation of LLL operator `sha3_32` * add sha3_32 compilation test * Add checks preventing assigning values on defining types. * Fix gas estimation error * Fix repeat LLL with <= 0 iteration * Add test for repat lll * Add depth check to with "set" statement * Require function visibility declaration * Add tests for public decorator * Add public decorator to tests (vyperlang#474) * Document function visibility requirements * Clarifies expectation in error message This would have helped me when I saw this error learning Viper for the first time. * Note internal or public decorator requirement * Fixes test with for function visibility. * Add the install instructions for the Viper snap This requries vyperlang#445, and enabling the continuous delivery on https://build.snapcraft.io * Allow for gas estimation tests for constants * Add gas estimation for create_with_code_of * ad logs to company.v.py with tests * document event in structure of a contract * move events before global declarations * remove unused import * types.py: Remove duplicated method Fix vyperlang#488 * Adds support -f bytecode_runtime. * cleans up test_logs * Use revert opcode for assert statements * Show lineno of base_type_conversion error Fix vyperlang#498 * Show lineno of undeclared function visibility Fix vyperlang#489 * Adds basic test for bytecode_runtime generation. * add clamp_nonzero to modulo arithemetic * Add modulo tests and refactor simple auction example * Use `with` to decrease repetition * Change vipercoin from returning false to throwing * Add check to as_num256 to make sure number is greater than 0 * Improve contributing .rst - Fixes a link that wasn't displaying correctly. - Makes some instructions more concise. - Changes old `:ref:building-from-source`, to link to installation instructions. * Added testing and deployment doc * Fix augassignment checks * Test for in list invalids * Remove repetitive error and fix typo * Begin adding built in erc20 external call functionality * Add implied erc20 token abi fucntionality * Add on chain market maker example * Test implied erc20 abi functionality * Update on chain market maker and erc20 abi * Change @internal decorator to @Private decorator. * Add support for logging a variable of list type. * Adds tests for logging of list types. * Fix for log packing on list variable. * Add error if log has wrong number of arguments * Add log test and improve bytes as input * Improve variable naming / fix bytes as input * Clean up tests * Adds Fix vyperlang#531. Check return type of lists match. * Adds more tests for logging of lists. * Adds Fix vyperlang#504 for clamping decimal literals correctly. * Use revert for clamps * Fix exponents with units * Create a contract data type * Remove .python-version, update .gitignore * Improve vipercoin example: link out to resources describing attack vectors * Test the contract data type * Update version of ethereum * Improves gas estimate on internal call. * Removed suicide keyword * Carry over add_gas_estimate in optimizer. * Adds gas estimation for internal calls. * Added test for invalid keyword * not official a language > officially * Changing notes to be indented blocks starting on the line after .. note:: https://sublime-and-sphinx-guide.readthedocs.io/en/latest/notes_warnings.html * Adds storage list logging support. * Adds test to check list logging is of correct (sub)type. * Splitting comments over two lines where necessary to fit on the page on readthedocs * Update to use conftest; fix some incorrect tests * Update Safe Remote Purchases: line numbers, minor edits * Updates from code review * Add modulo math checks * Adds support for logging bytes from storage. * Adds exception to limit to 32 bytes of bytes type logging (restriction for the time being). * virtualenv -p /usr/local/lib/python3.6/bin/python3 > virtualenv -p python3.6 Related: vyperlang#558 * Add a note on how to fix `fatal error: openssl/aes.h: No such file or directory` in the `make` output * removed extraneous backtick ` * Minor edits with ``num`` type > with the ``num`` type crowdfunding period is over - as determined> crowdfunding period is over—as determined * Minor edits voting add a comma > to vote, and each add a comma > to vote, or * Adds basic single list argument call functionality. * Improve for loop error * Adds test for logging a decimal list. * :ref:`function-calls` > :ref:`Function-calls` * Minor edits types.rst * Fixes handling of static array in call. - Also adds tests for many mixed cases of calling with a list parameter. * Adds test for mixed bytes - list calling arguments. * Add length check to event topics * Fix and test logging with units * Improve type parsing error message * Add valid call keyword list to utils * Add length check to event topics * Partial fix for vyperlang#590. Adds check for a minimum of one return statement. * Fixes test that were missing return statements. * Adds example of return checker behaving incorrectly. * Adds if statement block scoping. * Add blockscoping to for loop. * Add blockscope tests. * Update dockerfile to use slim image base * Remove commented out directives * Reduce num256_add gas cost * Tag built image as viper * Add built-in function docs * Fix on chain market maker * Add comments to on chain market maker * Change badges from viper to vyper * Fix rlp decoding loop memory * Fix call data copy gas estimation * Implement continue Add `continue` to pseudo_opcodes, LLL, and viper. * Fix example ERC20 token Discovered that it doesn't compile by trying to compile all of the example contracts in `examples/`. This fixes ERC20.v.py by resolving compiler complaints. * Add internal call arg count check * cleaned up linter errors under tests/compiler * cleaned up imports and replaced boolean assertion under test_simple_auction * fixed linter errors in tests/examples/company * fixed linter errors on tests/examples/market_maker * fixed linter errors under tests/exmaples/safe_remote_purchase * cleaned up linter errors tests/examples/tokens * fixed linter errors on tests/examples/voting * fixed linter errors on tests/examples/wallets * fixed linter errors in tests/parsers/features * test_extract32.py: renamed first function to test_extract32_extraction * fixed linter errors * cleaned up linter errors tests/parser * Adds test for passing list from storage. * Make blockscopes use set() instead of list(). * specified flake8 script on travis to include tests/ * cleaned up exception block for test_test_bytes * cleaned up bare except under test_arbitration_code * cleaned up bare imports to handle ValueOutOfBounds exception in tests/parser/features/test_constructor.py * cleaned up bare imports test_raw_call * test_test_slice4: cleaned up test assertions for raised exceptions * cleaned up bare excepts in test_extract32 * fixed linter error tests/parser/features/test_internal_call.py * setup.cfg: set flake8 exclusion only for docs * Fixes vyperlang#547, correct handling of units for exponent notation. * Adds tests for unit exponents. * edited travis script for flake8 * Fix err msg for functions without enough arguments * Add an error message for calls to undefined top-level functions Previously, the compiler would error ungracefully if an undefined top-level function was called, due to an unhandled case in `Expr.call`. The compiler now also makes suggestions when a non-existent top-level function is mistakenly called instead of a contract method. * Add `.gitattributes` syntax highlighting trick * Add .gitattributes file * Prevent mixed list type from occuring. * Fixes test that contain mixed list types. * pep8 fixes * Remove num256 greater than 0 check for bytes32 * Bump version: 0.0.2 → 0.0.3
i revisited this today while working on a fix for #3223. i think the issue is actually not that ifs inside of for loops are not analyseable. you can apply the same branching analysis -- that is, # valid return
for i in range(10):
if n == i:
return 1
else:
return 0
# do not need to add return statement here, for loop is guaranteed to terminate the issue now is that we now have for loops which might have 0 iterations, for example: xs: DynArray[uint256, 3] = []
for i: uint256 in xs: # never executes
return 1
# reachable! we could maybe apply one of two analyses depending on if we can prove the loop iterates at least 1 time. |
What's your issue about?
Currently you can have a return type set on a function, yet omit the return statement. Add a exception when this happens forcing the programming to add a return, if specified.
e.g.
How can it be fixed?
Off the top of my head, check parse_func.
Cute Animal Picture
The text was updated successfully, but these errors were encountered: