Skip to content
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

constants replaced before folding is finished #3097

Closed
ptrcarta opened this issue Sep 13, 2022 · 1 comment
Closed

constants replaced before folding is finished #3097

ptrcarta opened this issue Sep 13, 2022 · 1 comment

Comments

@ptrcarta
Copy link

Version Information

  • vyper Version (output of vyper --version): 0.3.6+commit.4a2124d0
  • OS: osx
  • Python Version (output of python --version): Python 3.9.13

What's your issue about?

Right now the following two contracts fail to compile:

#@version 0.3.6

a:constant(uint256) = as_wei_value(2*3, 'kwei')

@external
def foo() -> uint256:
    return a
#@version 0.3.6

a:constant(uint256[4]) = [as_wei_value(2*3, 'kwei'),1,2,3]

@external
def foo() -> uint256:
    return a[3]

full output of the error you received

traceback is similar for both contracts:

% vyper --verbose pietro/folding_eager_call.vy
Error compiling: pietro/folding_eager_call.vy
Traceback (most recent call last):
  File "/Users/pietro/dev/vyper/vyper_venv/bin/vyper", line 8, in <module>
    sys.exit(_parse_cli_args())
  File "/Users/pietro/dev/vyper/vyper/cli/vyper_compile.py", line 56, in _parse_cli_args
    return _parse_args(sys.argv[1:])
  File "/Users/pietro/dev/vyper/vyper/cli/vyper_compile.py", line 150, in _parse_args
    compiled = compile_files(
  File "/Users/pietro/dev/vyper/vyper/cli/vyper_compile.py", line 288, in compile_files
    compiler_data = vyper.compile_codes(
  File "/Users/pietro/dev/vyper/vyper/evm/opcodes.py", line 224, in _wrapper
    return fn(*args, **kwargs)
  File "/Users/pietro/dev/vyper/vyper/compiler/__init__.py", line 137, in compile_codes
    exc_handler(contract_name, exc)
  File "/Users/pietro/dev/vyper/vyper/cli/vyper_compile.py", line 184, in exc_handler
    raise exception
  File "/Users/pietro/dev/vyper/vyper/compiler/__init__.py", line 134, in compile_codes
    out[contract_name][output_format] = OUTPUT_FORMATS[output_format](compiler_data)
  File "/Users/pietro/dev/vyper/vyper/compiler/output.py", line 243, in build_bytecode_output
    return f"0x{compiler_data.bytecode.hex()}"
  File "/opt/homebrew/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/functools.py", line 993, in __get__
    val = self.func(instance)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 145, in bytecode
    return generate_bytecode(self.assembly, is_runtime=False)
  File "/opt/homebrew/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/functools.py", line 993, in __get__
    val = self.func(instance)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 137, in assembly
    return generate_assembly(self.ir_nodes, self.no_optimize)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 122, in ir_nodes
    ir, ir_runtime, sigs = self._ir_output
  File "/opt/homebrew/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/functools.py", line 993, in __get__
    val = self.func(instance)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 118, in _ir_output
    return generate_ir_nodes(self.global_ctx, self.no_optimize)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 113, in global_ctx
    return generate_global_context(self.vyper_module_folded, self.interface_codes)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 103, in vyper_module_folded
    module, storage_layout = self._folded_module
  File "/opt/homebrew/Cellar/[email protected]/3.9.13_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/functools.py", line 993, in __get__
    val = self.func(instance)
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 97, in _folded_module
    return generate_folded_ast(
  File "/Users/pietro/dev/vyper/vyper/compiler/phases.py", line 220, in generate_folded_ast
    vy_ast.folding.fold(vyper_module_folded)
  File "/Users/pietro/dev/vyper/vyper/ast/folding.py", line 41, in fold
    changed_nodes += replace_literal_ops(vyper_module)
  File "/Users/pietro/dev/vyper/vyper/ast/folding.py", line 71, in replace_literal_ops
    vyper_module.replace_in_tree(node, new_node)
  File "/Users/pietro/dev/vyper/vyper/ast/nodes.py", line 606, in replace_in_tree
    raise CompilerPanic("Node to be replaced does not exist within parent children")
vyper.exceptions.CompilerPanic: Node to be replaced does not exist within parent children

This is an unhandled internal compiler error. Please create an issue on Github to notify the developers.
https://github.com/vyperlang/vyper/issues/new?template=bug.md

How can it be fixed?

This is caused by constant folding replacing constant names with the value of the constant definition before the folding for that constant is finished. so a constant value is used even if it is of type vy_ast.Call and not a constant structure. There's a check in folding.py for is_struct but I don't think it is in the right place.

I've prepared a small pr for this issue. It manages to get these examples to compile but I'm not sure it will not introduce other issues, so double check. I didn't remove the old is_struct code in replace_constant, maybe it's there for a reason, but I don't think it's working.

@charles-cooper
Copy link
Member

fixed as of #3669

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants