Repository: vyperlang/vyper

Issue:
Convert function takes string instead of type for conversion to
### What's your issue about?
If you forget to add quotes to the type you want to convert to, Vyper will give an unhelpful error:
```python
convert(some_int128, uint256)
# raises:
#    AttributeError: 'Name' object has no attribute 's'
```

### How can it be fixed?
So, catching this error might work out to fix this issue, but I think the underlying issue is that the second argument (`convertTo`) is a string instead of a typename. This actually makes it a little more unintuitive to write conversions as you could misspell the name and not get visual feedback from your IDE (assuming you have syntax highlighting up)

I would suggest turning this into a VIP to modify the syntax of convert such that a valid typename is supplied as the second argument

#### Cute Animal Picture
![pony](https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Gracie-rhs2005.jpg/1200px-Gracie-rhs2005.jpg)



Discussion:
Yes agree, moving to convert(a, int128) without quotes is the way to go.
Starting on this.
cc @haydenadams

Resolving patch:
diff --git a/vyper/types/convert.py b/vyper/types/convert.py
--- a/vyper/types/convert.py
+++ b/vyper/types/convert.py
@@ -1,3 +1,6 @@
+import ast
+import warnings
+
 from vyper.functions.signature import (
     signature
 )
@@ -9,6 +12,7 @@
 from vyper.exceptions import (
     InvalidLiteralException,
     TypeMismatchException,
+    ParserException,
 )
 from vyper.types import (
     BaseType,
@@ -23,7 +27,7 @@
 )
 
 
-@signature(('uint256', 'bytes32', 'bytes'), 'str_literal')
+@signature(('uint256', 'bytes32', 'bytes'), '*')
 def to_int128(expr, args, kwargs, context):
     in_node = args[0]
     typ, len = get_type(in_node)
@@ -38,7 +42,7 @@ def to_int128(expr, args, kwargs, context):
         return byte_array_to_num(in_node, expr, 'int128')
 
 
-@signature(('num_literal', 'int128', 'bytes32', 'address'), 'str_literal')
+@signature(('num_literal', 'int128', 'bytes32', 'address'), '*')
 def to_uint256(expr, args, kwargs, context):
     in_node = args[0]
     input_type, len = get_type(in_node)
@@ -60,7 +64,7 @@ def to_uint256(expr, args, kwargs, context):
         raise InvalidLiteralException("Invalid input for uint256: %r" % in_node, expr)
 
 
-@signature(('int128', 'uint256'), 'str_literal')
+@signature(('int128', 'uint256'), '*')
 def to_decimal(expr, args, kwargs, context):
     input = args[0]
     if input.typ.typ == 'uint256':
@@ -76,7 +80,7 @@ def to_decimal(expr, args, kwargs, context):
         )
 
 
-@signature(('int128', 'uint256', 'address', 'bytes'), 'str_literal')
+@signature(('int128', 'uint256', 'address', 'bytes'), '*')
 def to_bytes32(expr, args, kwargs, context):
     input = args[0]
     typ, len = get_type(input)
@@ -96,11 +100,23 @@ def to_bytes32(expr, args, kwargs, context):
 
 
 def convert(expr, context):
-    output_type = expr.args[1].s
+
+    if isinstance(expr.args[1], ast.Str):
+        warnings.warn(
+            "String parameter has been removed, see VIP1026). "
+            "Use a vyper type instead.",
+            DeprecationWarning
+        )
+
+    if isinstance(expr.args[1], ast.Name):
+        output_type = expr.args[1].id
+    else:
+        raise ParserException("Invalid conversion type, use valid vyper type.", expr)
+
     if output_type in conversion_table:
         return conversion_table[output_type](expr, context)
     else:
-        raise Exception("Conversion to {} is invalid.".format(output_type))
+        raise ParserException("Conversion to {} is invalid.".format(output_type), expr)
 
 
 conversion_table = {


Test patch:
diff --git a/tests/parser/exceptions/test_invalid_literal_exception.py b/tests/parser/exceptions/test_invalid_literal_exception.py
--- a/tests/parser/exceptions/test_invalid_literal_exception.py
+++ b/tests/parser/exceptions/test_invalid_literal_exception.py
@@ -80,17 +80,17 @@ def foo():
     """
 @public
 def foo():
-    x: uint256 = convert(821649876217461872458712528745872158745214187264875632587324658732648753245328764872135671285218762145, 'uint256')
+    x: uint256 = convert(821649876217461872458712528745872158745214187264875632587324658732648753245328764872135671285218762145, uint256)
     """,
     """
 @public
 def foo():
-    x = convert(-1, 'uint256')
+    x = convert(-1, uint256)
     """,
     """
 @public
 def foo():
-    x = convert(3.1415, 'uint256')
+    x = convert(3.1415, uint256)
     """,
     """
 # Test decimal limit.
diff --git a/tests/parser/features/iteration/test_break.py b/tests/parser/features/iteration/test_break.py
--- a/tests/parser/features/iteration/test_break.py
+++ b/tests/parser/features/iteration/test_break.py
@@ -57,7 +57,7 @@ def test_break_test_3(get_contract_with_gas_estimation):
     break_test_3 = """
 @public
 def log(n: int128) -> int128:
-    c: decimal = convert(n, 'decimal')
+    c: decimal = convert(n, decimal)
     output: int128 = 0
     for i in range(40):
         if c < 10.0:
diff --git a/tests/parser/functions/test_ceil.py b/tests/parser/functions/test_ceil.py
--- a/tests/parser/functions/test_ceil.py
+++ b/tests/parser/functions/test_ceil.py
@@ -33,7 +33,7 @@ def fos() -> int128:
 def fou() -> int128:
     a: int128 = 305
     b: int128 = 100
-    c: decimal = convert(a, 'decimal') / convert(b, 'decimal')
+    c: decimal = convert(a, decimal) / convert(b, decimal)
     return ceil(c)
     """
 
diff --git a/tests/parser/functions/test_convert.py b/tests/parser/functions/test_convert.py
--- a/tests/parser/functions/test_convert.py
+++ b/tests/parser/functions/test_convert.py
@@ -10,28 +10,29 @@ def test_convert_to_num(get_contract_with_gas_estimation, assert_tx_failed):
 @public
 def uint256_to_num(inp: uint256) -> (int128, int128):
     self.a = inp
-    memory: int128  = convert(inp, 'int128')
-    storage: int128 = convert(self.a, 'int128')
+    memory: int128  = convert(inp, int128)
+    storage: int128 = convert(self.a, int128)
     return  memory, storage
 
 @public
 def bytes32_to_num() -> (int128, int128):
     self.b = 0x0000000000000000000000000000000000000000000000000000000000000001
-    literal: int128 = convert(0x0000000000000000000000000000000000000000000000000000000000000001, 'int128')
-    storage: int128 = convert(self.b, 'int128')
+    literal: int128 = convert(0x0000000000000000000000000000000000000000000000000000000000000001, int128)
+    storage: int128 = convert(self.b, int128)
     return literal, storage
 
 @public
 def bytes_to_num() -> (int128, int128):
     self.c = 'a'
-    literal: int128 = convert('a', 'int128')
-    storage: int128 = convert(self.c, 'int128')
+    literal: int128 = convert('a', int128)
+    storage: int128 = convert(self.c, int128)
     return literal, storage
 
 @public
 def zero_bytes(inp: bytes[1]) -> int128:
-    return convert(inp, 'int128')
-"""
+    return convert(inp, int128)
+    """
+
     c = get_contract_with_gas_estimation(code)
     assert c.uint256_to_num(1) == [1, 1]
     assert c.bytes32_to_num() == [1, 1]
@@ -51,18 +52,19 @@ def test_convert_to_uint256(get_contract, assert_tx_failed):
 @public
 def int128_to_uint256(inp: int128) -> (uint256, uint256, uint256):
     self.a = inp
-    memory: uint256  = convert(inp, "uint256")
-    storage: uint256 = convert(self.a, "uint256")
-    literal: uint256 = convert(1, "uint256")
+    memory: uint256  = convert(inp, uint256)
+    storage: uint256 = convert(self.a, uint256)
+    literal: uint256 = convert(1, uint256)
     return  memory, storage, literal
 
 @public
 def bytes32_to_uint256() -> (uint256, uint256):
     self.b = 0x0000000000000000000000000000000000000000000000000000000000000001
-    literal: uint256 = convert(0x0000000000000000000000000000000000000000000000000000000000000001, "uint256")
-    storage: uint256 = convert(self.b, "uint256")
+    literal: uint256 = convert(0x0000000000000000000000000000000000000000000000000000000000000001, uint256)
+    storage: uint256 = convert(self.b, uint256)
     return literal, storage
-"""
+    """
+
     c = get_contract(code)
     assert c.int128_to_uint256(1) == [1, 1, 1]
     assert c.bytes32_to_uint256() == [1, 1]
@@ -76,9 +78,9 @@ def test_convert_to_decimal(get_contract, assert_tx_failed):
 @public
 def int128_to_decimal(inp: int128) -> (decimal, decimal, decimal):
     self.a = inp
-    memory: decimal = convert(inp, "decimal")
-    storage: decimal = convert(self.a, "decimal")
-    literal: decimal = convert(1, "decimal")
+    memory: decimal = convert(inp, decimal)
+    storage: decimal = convert(self.a, decimal)
+    literal: decimal = convert(1, decimal)
     return  memory, storage, literal
 """
     c = get_contract(code)
@@ -95,31 +97,31 @@ def test_convert_to_bytes32(w3, get_contract_with_gas_estimation, bytes_helper):
 @public
 def int128_to_bytes32(inp: int128) -> (bytes32, bytes32, bytes32):
     self.a = inp
-    memory: bytes32 = convert(inp, "bytes32")
-    storage: bytes32 = convert(self.a, "bytes32")
-    literal: bytes32 = convert(1, "bytes32")
+    memory: bytes32 = convert(inp, bytes32)
+    storage: bytes32 = convert(self.a, bytes32)
+    literal: bytes32 = convert(1, bytes32)
     return  memory, storage, literal
 
 @public
 def uint256_to_bytes32(inp: uint256) -> (bytes32, bytes32, bytes32):
     self.b = inp
-    memory: bytes32 = convert(inp, "bytes32")
-    storage: bytes32 = convert(self.b, "bytes32")
-    literal: bytes32 = convert(1, "bytes32")
+    memory: bytes32 = convert(inp, bytes32)
+    storage: bytes32 = convert(self.b, bytes32)
+    literal: bytes32 = convert(1, bytes32)
     return  memory, storage, literal
 
 @public
 def address_to_bytes32(inp: address) -> (bytes32, bytes32):
     self.c = inp
-    memory: bytes32 = convert(inp, "bytes32")
-    storage: bytes32 = convert(self.c, "bytes32")
+    memory: bytes32 = convert(inp, bytes32)
+    storage: bytes32 = convert(self.c, bytes32)
     return  memory, storage
 
 @public
 def bytes_to_bytes32(inp: bytes[32]) -> (bytes32, bytes32):
     self.d = inp
-    memory: bytes32 = convert(inp, "bytes32")
-    storage: bytes32 = convert(self.d, "bytes32")
+    memory: bytes32 = convert(inp, bytes32)
+    storage: bytes32 = convert(self.d, bytes32)
     return  memory, storage
 """
     c = get_contract_with_gas_estimation(code)
@@ -134,11 +136,11 @@ def test_uint256_decimal(assert_tx_failed, get_contract_with_gas_estimation):
 @public
 def test_variable() -> bool:
     a: uint256 = 1000
-    return convert(a, 'decimal') == 1000.0
+    return convert(a, decimal) == 1000.0
 
 @public
 def test_passed_variable(a: uint256) -> decimal:
-    return convert(a, 'decimal')
+    return convert(a, decimal)
     """
 
     c = get_contract_with_gas_estimation(code)
@@ -159,7 +161,7 @@ def test_convert_to_uint256_units(get_contract, assert_tx_failed):
 @public
 def test() -> int128(meter):
     b: uint256(meter) = 1234
-    a: int128(meter) = convert(b, "int128")
+    a: int128(meter) = convert(b, int128)
     return a
     """
 
@@ -176,7 +178,7 @@ def test_convert_to_int128_units(get_contract, assert_tx_failed):
 @public
 def test() -> uint256(meter):
     b: int128(meter) = 4321
-    a: uint256(meter) = convert(b, "uint256")
+    a: uint256(meter) = convert(b, uint256)
     return a
     """
 
@@ -192,13 +194,13 @@ def test_convert_to_int128_decimal_units(get_contract, assert_tx_failed):
 
 @public
 def test() -> decimal(meter):
-    a: decimal(meter) = convert(5001, "decimal")
+    a: decimal(meter) = convert(5001, decimal)
     return a
 
 @public
 def test2() -> decimal(meter):
     b: int128(meter) = 1234
-    a: decimal(meter) = convert(b, "decimal")
+    a: decimal(meter) = convert(b, decimal)
     return a
     """
 
@@ -214,16 +216,16 @@ def test_convert_address_to_uint256(w3, get_contract):
 
 @public
 def conv1(a: address) -> uint256:
-    return convert(a, 'uint256')
+    return convert(a, uint256)
 
 @public
 def conv2() -> uint256:
     self.stor_a = 0x744d70FDBE2Ba4CF95131626614a1763DF805B9E
-    return convert(self.stor_a, 'uint256')
+    return convert(self.stor_a, uint256)
 
 @public
 def conv3() -> uint256:
-    return convert(0x744d70FDBE2Ba4CF95131626614a1763DF805B9E, 'uint256')
+    return convert(0x744d70FDBE2Ba4CF95131626614a1763DF805B9E, uint256)
     """
 
     c = get_contract(code)
diff --git a/tests/parser/functions/test_convert_int128.py b/tests/parser/functions/test_convert_int128.py
--- a/tests/parser/functions/test_convert_int128.py
+++ b/tests/parser/functions/test_convert_int128.py
@@ -5,7 +5,7 @@ def test_convert_bytes32_to_num_overflow(assert_tx_failed, get_contract_with_gas
 @public
 def test1():
     y: bytes32 = 0x1000000000000000000000000000000000000000000000000000000000000000
-    x: int128 = convert(y, 'int128')
+    x: int128 = convert(y, int128)
     """
 
     c = get_contract_with_gas_estimation(code)
@@ -16,7 +16,7 @@ def test_convert_address_to_num(assert_compile_failed, get_contract_with_gas_est
     code = """
 @public
 def test2():
-    x: int128 = convert(msg.sender, 'int128')
+    x: int128 = convert(msg.sender, int128)
     """
 
     assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
@@ -27,7 +27,7 @@ def test_convert_out_of_range(assert_compile_failed, get_contract_with_gas_estim
 @public
 def test2():
     x: int128
-    x = convert(340282366920938463463374607431768211459, 'int128')
+    x = convert(340282366920938463463374607431768211459, int128)
     """
 
     assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
diff --git a/tests/parser/functions/test_convert_uint256.py b/tests/parser/functions/test_convert_uint256.py
--- a/tests/parser/functions/test_convert_uint256.py
+++ b/tests/parser/functions/test_convert_uint256.py
@@ -1,9 +1,10 @@
+
 def test_convert_to_uint256_with_negative_num(assert_compile_failed, get_contract_with_gas_estimation):
     code = """
 @public
 def foo() -> uint256:
-    return convert(1-2, 'uint256')
-"""
+    return convert(1-2, uint256)
+    """
     assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
 
 
@@ -11,8 +12,8 @@ def test_convert_to_uint256_with_negative_input(assert_tx_failed, get_contract_w
     code = """
 @public
 def foo(x: int128) -> uint256:
-    return convert(x, 'uint256')
-"""
+    return convert(x, uint256)
+    """
     c = get_contract_with_gas_estimation(code)
     assert_tx_failed(lambda: c.foo(-1))
 
@@ -21,8 +22,8 @@ def test_convert_to_uint256_with_bytes32(get_contract_with_gas_estimation):
     code = """
 @public
 def foo() -> uint256:
-    return convert(convert(-1, 'bytes32'), 'uint256')
-"""
+    return convert(convert(-1, bytes32), uint256)
+    """
 
     c = get_contract_with_gas_estimation(code)
     assert c.foo() == 2 ** 256 - 1
diff --git a/tests/parser/functions/test_ecrecover.py b/tests/parser/functions/test_ecrecover.py
--- a/tests/parser/functions/test_ecrecover.py
+++ b/tests/parser/functions/test_ecrecover.py
@@ -10,9 +10,9 @@ def test_ecrecover(h: bytes32, v:uint256, r:uint256, s:uint256) -> address:
 @public
 def test_ecrecover2() -> address:
     return ecrecover(0x3535353535353535353535353535353535353535353535353535353535353535,
-                     convert(28, 'uint256'),
-                     convert(63198938615202175987747926399054383453528475999185923188997970550032613358815, 'uint256'),
-                     convert(6577251522710269046055727877571505144084475024240851440410274049870970796685, 'uint256'))
+                     convert(28, uint256),
+                     convert(63198938615202175987747926399054383453528475999185923188997970550032613358815, uint256),
+                     convert(6577251522710269046055727877571505144084475024240851440410274049870970796685, uint256))
     """
 
     c = get_contract_with_gas_estimation(ecrecover_test)
diff --git a/tests/parser/functions/test_floor.py b/tests/parser/functions/test_floor.py
--- a/tests/parser/functions/test_floor.py
+++ b/tests/parser/functions/test_floor.py
@@ -65,7 +65,7 @@ def x_floor() -> int128:
 @public
 def foo() -> int128:
     a: int128 = -65
-    b: decimal = convert(a, 'decimal') / 10.0
+    b: decimal = convert(a, decimal) / 10.0
     return floor(b)
 
 @public
diff --git a/tests/parser/functions/test_method_id.py b/tests/parser/functions/test_method_id.py
--- a/tests/parser/functions/test_method_id.py
+++ b/tests/parser/functions/test_method_id.py
@@ -1,3 +1,5 @@
+
+
 def test_method_id_test(get_contract_with_gas_estimation):
     method_id_test = """
 @public
@@ -6,8 +8,8 @@ def double(x: int128) -> int128:
 
 @public
 def returnten() -> int128:
-    ans: bytes[32] = raw_call(self, concat(method_id("double(int128)", bytes[4]), convert(5, 'bytes32')), gas=50000, outsize=32)
-    return convert(convert(ans, 'bytes32'), 'int128')
+    ans: bytes[32] = raw_call(self, concat(method_id("double(int128)", bytes[4]), convert(5, bytes32)), gas=50000, outsize=32)
+    return convert(convert(ans, bytes32), int128)
     """
     c = get_contract_with_gas_estimation(method_id_test)
     assert c.returnten() == 10
diff --git a/tests/parser/functions/test_minmax.py b/tests/parser/functions/test_minmax.py
--- a/tests/parser/functions/test_minmax.py
+++ b/tests/parser/functions/test_minmax.py
@@ -9,7 +9,7 @@ def foo() -> decimal:
 
 @public
 def goo() -> uint256:
-    return min(convert(3, 'uint256'), convert(5, 'uint256')) + max(convert(40, 'uint256'), convert(80, 'uint256'))
+    return min(convert(3, uint256), convert(5, uint256)) + max(convert(40, uint256), convert(80, uint256))
     """
 
     c = get_contract_with_gas_estimation(minmax_test)
diff --git a/tests/parser/functions/test_slice.py b/tests/parser/functions/test_slice.py
--- a/tests/parser/functions/test_slice.py
+++ b/tests/parser/functions/test_slice.py
@@ -99,7 +99,7 @@ def test_slice_at_end(get_contract):
     code = """
 @public
 def ret10_slice() -> bytes[10]:
-    b: bytes[32] = concat(convert(65, 'bytes32'), '')
+    b: bytes[32] = concat(convert(65, bytes32), '')
     c: bytes[10] = slice(b, start=31, len=1)
     return c
     """
diff --git a/tests/parser/globals/test_setters.py b/tests/parser/globals/test_setters.py
--- a/tests/parser/globals/test_setters.py
+++ b/tests/parser/globals/test_setters.py
@@ -135,7 +135,7 @@ def test_type_converter_setter_test(get_contract_with_gas_estimation):
 def foo() -> int128:
     self.mom = {a: [{c: 1}, {c: 2}, {c: 3}], b: 4}
     self.non = self.mom
-    return floor(self.non.a[0].c + self.non.a[1].c * 10.0 + self.non.a[2].c * 100.0 + convert(self.non.b, 'decimal') * 1000.0)
+    return floor(self.non.a[0].c + self.non.a[1].c * 10.0 + self.non.a[2].c * 100.0 + convert(self.non.b, decimal) * 1000.0)
 
 @public
 def goo() -> int128:
diff --git a/tests/parser/syntax/test_as_uint256.py b/tests/parser/syntax/test_as_uint256.py
--- a/tests/parser/syntax/test_as_uint256.py
+++ b/tests/parser/syntax/test_as_uint256.py
@@ -9,7 +9,7 @@
     """
 @public
 def convert2(inp: uint256) -> address:
-    return convert(inp, 'bytes32')
+    return convert(inp, bytes32)
     """,
     """
 @public
@@ -30,17 +30,17 @@ def test_as_wei_fail(bad_code):
     """
 @public
 def convert1(inp: bytes32) -> uint256:
-    return convert(inp, 'uint256')
+    return convert(inp, uint256)
     """,
     """
 @public
 def convert1(inp: bytes32) -> uint256:
-    return convert(inp, 'uint256')
+    return convert(inp, uint256)
     """,
     """
 @public
 def convert2(inp: uint256) -> bytes32:
-    return convert(inp, 'bytes32')
+    return convert(inp, bytes32)
     """
 ]
 
diff --git a/tests/parser/syntax/test_bytes.py b/tests/parser/syntax/test_bytes.py
--- a/tests/parser/syntax/test_bytes.py
+++ b/tests/parser/syntax/test_bytes.py
@@ -95,7 +95,7 @@ def foo(x: bytes[100]) -> bytes[150]:
     """
 @public
 def convert2(inp: uint256) -> bytes32:
-    return convert(inp, 'bytes32')
+    return convert(inp, bytes32)
     """,
     """
 @public
diff --git a/tests/parser/syntax/test_functions_call.py b/tests/parser/syntax/test_functions_call.py
--- a/tests/parser/syntax/test_functions_call.py
+++ b/tests/parser/syntax/test_functions_call.py
@@ -8,14 +8,14 @@
     """
 @public
 def foo() -> uint256:
-    doesnotexist(2, 'uint256')
-    return convert(2, 'uint256')
+    doesnotexist(2, uint256)
+    return convert(2, uint256)
     """,
     """
 @public
 def foo() -> uint256:
-    convert(2, 'uint256')
-    return convert(2, 'uint256')
+    convert(2, uint256)
+    return convert(2, uint256)
 
     """
 ]
@@ -36,7 +36,7 @@ def test_raw_call_fail(bad_code):
     """
 @public
 def foo() -> uint256:
-    return convert(2, 'uint256')
+    return convert(2, uint256)
     """
 ]
 
diff --git a/tests/parser/types/numbers/test_uint256.py b/tests/parser/types/numbers/test_uint256.py
--- a/tests/parser/types/numbers/test_uint256.py
+++ b/tests/parser/types/numbers/test_uint256.py
@@ -125,10 +125,10 @@ def test_modmul(get_contract_with_gas_estimation):
     modexper = """
 @public
 def exponential(base: uint256, exponent: uint256, modulus: uint256) -> uint256:
-    o: uint256 = convert(1, 'uint256')
+    o: uint256 = convert(1, uint256)
     for i in range(256):
         o = uint256_mulmod(o, o, modulus)
-        if bitwise_and(exponent, shift(convert(1, 'uint256'), 255 - i)) != convert(0, 'uint256'):
+        if bitwise_and(exponent, shift(convert(1, uint256), 255 - i)) != convert(0, uint256):
             o = uint256_mulmod(o, base, modulus)
     return o
     """
diff --git a/tests/parser/types/test_bytes.py b/tests/parser/types/test_bytes.py
--- a/tests/parser/types/test_bytes.py
+++ b/tests/parser/types/test_bytes.py
@@ -170,12 +170,12 @@ def test_convert_bytes_to_num_code(get_contract_with_gas_estimation, assert_tx_f
 
 @public
 def foo(x: bytes[32]) -> int128:
-    return convert(x, 'int128')
+    return convert(x, int128)
 
 @public
 def bar_storage() -> int128:
     self.astor = "a"
-    return convert(self.astor, 'int128')
+    return convert(self.astor, int128)
     """
 
     c = get_contract_with_gas_estimation(bytes_to_num_code)