Skip to content

Folding Not Supported in Certain Locations #4190

@ritzdorf

Description

@ritzdorf

Version Information

  • vyper Version (output of vyper --version OR linkable commit hash vyperlang/vyper@): b43ffac

Issue Description

Several Vyper constructs require or can be optimized if constant values
are provided. To achieve this, AST nodes can be folded to constants by
the compiler, however, the following locations do not support folding:

  • length in slice(x, start, length) when x is msg.data or
    address.code:

    • isinstance(parent.args[2], vy_ast.Int) in
      _validate_msg_data_attribute()
    • isinstance(parent.args[2], vy_ast.Int) in
      _validate_address_code()
  • length in slice(x, start, length):

    • if length_literal is not None condition in
      Slice.fetch_call_return()
  • index in variable[index] when the variable is an array.

    • isinstance(node, vy_ast.Int) in
      _SequenceT.validate_index_type()
  • index in variable[index] when the variable is a tuple.

    • not isinstance(node, vy_ast.Int) in
      TupleT.validate_index_type()
  • x or y in x ** y:

    • left, right = _get_lr() in NumericT.validate_numeric_op()
  • x in convert(x, T)

    • _convert._to_int(), _convert.to_decimal() and
      _convert._cast_bytestring() does not check if expr has a
      folded value.
  • topic in raw_log(topic, data) .

    • not isinstance(node.args[0], vy_ast.List) in
      RawLog.infer_arg_types()

POC

The following example demonstrates the different issues.

@external
def foo():
    x: Bytes[32] = slice(msg.data, 0, 31 + 1) # StructureException
@external
def foo(tuple: (uint256,uint256)) -> uint256:
    return tuple[0+1] # InvalidType
k: constant(Bytes[3]) = b'aaa'
@external
def foo():

    a: Bytes[2] = convert (k, Bytes[2]) # compiles instead of failing
    b: Bytes[2] = convert (b'aaa', Bytes[2]) # TypeMismatch
a: constant(uint256) = 12
@external
def foo():
    # The following check is inserted by the compiler although it is not necessary
    # [assert, [iszero, [shr, 128, 12 <12>]]],
    b: uint128 = convert (a, uint128)
topic: constant(bytes32) = 0x1212121212121210212801291212121212121210121212121212121212121212
@external
def foo():
    raw_log([[topic]][0], b'') # InvalidType

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions