Repository: vyperlang/vyper

Issue:
VIP: len return type should be uint256
## Simple Summary
The builtin `len` function should return `uint256`.

## Motivation
It is impossible to have a negative length. As such, `uint256` is the type I would expect to receive from this function. 

## Specification

```python
len(b: bytes) → uint256
```

## Backwards Compatibility
It's a small but breaking change.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)



Discussion:

Resolving patch:
diff --git a/vyper/functions/functions.py b/vyper/functions/functions.py
--- a/vyper/functions/functions.py
+++ b/vyper/functions/functions.py
@@ -342,7 +342,7 @@ class Len(_SimpleBuiltinFunction):
 
     _id = "len"
     _inputs = [("b", ArrayValueAbstractType())]
-    _return_type = Int128Definition()
+    _return_type = Uint256Definition()
 
     def evaluate(self, node):
         validate_call_args(node, 1)
diff --git a/vyper/parser/parser_utils.py b/vyper/parser/parser_utils.py
--- a/vyper/parser/parser_utils.py
+++ b/vyper/parser/parser_utils.py
@@ -262,9 +262,9 @@ def byte_array_to_num(
 
 def get_length(arg):
     if arg.location == "memory":
-        return LLLnode.from_list(["mload", arg], typ=BaseType("int128"))
+        return LLLnode.from_list(["mload", arg], typ=BaseType("uint256"))
     elif arg.location == "storage":
-        return LLLnode.from_list(["sload", ["sha3_32", arg]], typ=BaseType("int128"))
+        return LLLnode.from_list(["sload", ["sha3_32", arg]], typ=BaseType("uint256"))
 
 
 def getpos(node):


Test patch:
diff --git a/tests/functions/folding/test_len.py b/tests/functions/folding/test_len.py
--- a/tests/functions/folding/test_len.py
+++ b/tests/functions/folding/test_len.py
@@ -8,7 +8,7 @@
 def test_len_string(get_contract, length):
     source = """
 @public
-def foo(a: string[1024]) -> int128:
+def foo(a: string[1024]) -> uint256:
     return len(a)
     """
     contract = get_contract(source)
@@ -26,7 +26,7 @@ def foo(a: string[1024]) -> int128:
 def test_len_bytes(get_contract, length):
     source = """
 @public
-def foo(a: bytes[1024]) -> int128:
+def foo(a: bytes[1024]) -> uint256:
     return len(a)
     """
     contract = get_contract(source)
@@ -44,7 +44,7 @@ def foo(a: bytes[1024]) -> int128:
 def test_len_hex(get_contract, length):
     source = """
 @public
-def foo(a: bytes[1024]) -> int128:
+def foo(a: bytes[1024]) -> uint256:
     return len(a)
     """
     contract = get_contract(source)
diff --git a/tests/parser/features/test_constructor.py b/tests/parser/features/test_constructor.py
--- a/tests/parser/features/test_constructor.py
+++ b/tests/parser/features/test_constructor.py
@@ -38,14 +38,14 @@ def get_twox() -> int128:
 
 def test_constructor_advanced_code2(get_contract_with_gas_estimation):
     constructor_advanced_code2 = """
-comb: int128
+comb: uint256
 
 @public
-def __init__(x: int128[2], y: bytes[3], z: int128):
+def __init__(x: uint256[2], y: bytes[3], z: uint256):
     self.comb = x[0] * 1000 + x[1] * 100 + len(y) * 10 + z
 
 @public
-def get_comb() -> int128:
+def get_comb() -> uint256:
     return self.comb
     """
     c = get_contract_with_gas_estimation(constructor_advanced_code2, *[[5, 7], b"dog", 8])
diff --git a/tests/parser/features/test_internal_call.py b/tests/parser/features/test_internal_call.py
--- a/tests/parser/features/test_internal_call.py
+++ b/tests/parser/features/test_internal_call.py
@@ -60,11 +60,11 @@ def return_hash_of_cow_x_30() -> bytes32:
     return self._hashy2(b"cowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcow")  # noqa: E501
 
 @private
-def _len(x: bytes[100]) -> int128:
+def _len(x: bytes[100]) -> uint256:
     return len(x)
 
 @public
-def returnten() -> int128:
+def returnten() -> uint256:
     return self._len(b"badminton!")
     """
 
diff --git a/tests/parser/functions/test_length.py b/tests/parser/functions/test_length.py
--- a/tests/parser/functions/test_length.py
+++ b/tests/parser/functions/test_length.py
@@ -3,7 +3,7 @@ def test_test_length(get_contract_with_gas_estimation):
 y: bytes[10]
 
 @public
-def foo(inp: bytes[10]) -> int128:
+def foo(inp: bytes[10]) -> uint256:
     x: bytes[5] = slice(inp,1, 5)
     self.y = slice(inp, 2, 4)
     return len(inp) * 100 + len(x) * 10 + len(self.y)
diff --git a/tests/parser/integration/test_basics.py b/tests/parser/integration/test_basics.py
--- a/tests/parser/integration/test_basics.py
+++ b/tests/parser/integration/test_basics.py
@@ -17,27 +17,3 @@ def foo(x: int128) -> int128:
     """
     c = get_contract_with_gas_estimation(basic_code)
     assert c.foo(9) == 18
-
-
-def test_selfcall_code_3(get_contract_with_gas_estimation, keccak):
-    selfcall_code_3 = """
-@private
-def _hashy2(x: bytes[100]) -> bytes32:
-    return keccak256(x)
-
-@public
-def return_hash_of_cow_x_30() -> bytes32:
-    return self._hashy2(b"cowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcow")  # noqa: E501
-
-@private
-def _len(x: bytes[100]) -> int128:
-    return len(x)
-
-@public
-def returnten() -> int128:
-    return self._len(b"badminton!")
-    """
-
-    c = get_contract_with_gas_estimation(selfcall_code_3)
-    assert c.return_hash_of_cow_x_30() == keccak(b"cow" * 30)
-    assert c.returnten() == 10
diff --git a/tests/parser/syntax/test_len.py b/tests/parser/syntax/test_len.py
--- a/tests/parser/syntax/test_len.py
+++ b/tests/parser/syntax/test_len.py
@@ -7,12 +7,12 @@
 fail_list = [
     """
 @public
-def foo(inp: int128) -> int128:
+def foo(inp: bytes[4]) -> int128:
     return len(inp)
     """,
     """
 @public
-def foo(inp: int128) -> address:
+def foo(inp: int128) -> uint256:
     return len(inp)
     """,
 ]
@@ -32,12 +32,12 @@ def test_block_fail(bad_code):
 valid_list = [
     """
 @public
-def foo(inp: bytes[10]) -> int128:
+def foo(inp: bytes[10]) -> uint256:
     return len(inp)
     """,
     """
 @public
-def foo(inp: string[10]) -> int128:
+def foo(inp: string[10]) -> uint256:
     return len(inp)
     """,
 ]