Repository: vyperlang/vyper

Issue:
Disallow implicit conversion during comparison
### What's your issue about?
Vyper will do implicit conversion during comparison (i.e., `int128` to `decimal` if one of the argument is `int128` and the other is `decimal`).  However, this behavior would cause [problems](https://github.com/ethereum/casper/issues/67). It is better to only allow strict comparison. The developer should explicitly convert the arguments and make sure that the two arguments are of the same type.

### How can it be fixed?
Remove the implicit conversion logic in the `compare` method in `expr.py`.

#### Cute Animal Picture

![image](https://user-images.githubusercontent.com/5641590/38141628-ab3f8b5e-33fe-11e8-999c-46ac6ff41238.png)




Discussion:
Agreed
Merge with https://github.com/ethereum/vyper/issues/716, as a VIP ;)
@yzhang90 I am busy implementing this now, does this mean - we only need to make explicit conversion necessary for comparison ? Other arithmetic can still use implicit conversion?
I think the overall strategy was to disallow implicit conversions between different integer types, except with literals.

Resolving patch:
diff --git a/vyper/parser/expr.py b/vyper/parser/expr.py
--- a/vyper/parser/expr.py
+++ b/vyper/parser/expr.py
@@ -397,15 +397,16 @@ def compare(self):
         if not is_numeric_type(left.typ) or not is_numeric_type(right.typ):
             if op not in ('eq', 'ne'):
                 raise TypeMismatchException("Invalid type for comparison op", self.expr)
-        ltyp, rtyp = left.typ.typ, right.typ.typ
-        if ltyp == rtyp:
+        left_type, right_type = left.typ.typ, right.typ.typ
+        if (left_type in ('decimal', 'int128') or right_type in ('decimal', 'int128')) and left_type != right_type:
+            raise TypeMismatchException(
+                'Implicit conversion from {} to {} disallowed, please convert.'.format(left_type, right_type),
+                self.expr
+            )
+        if left_type == right_type:
             return LLLnode.from_list([op, left, right], typ='bool', pos=getpos(self.expr))
-        elif ltyp == 'decimal' and rtyp == 'int128':
-            return LLLnode.from_list([op, left, ['mul', right, DECIMAL_DIVISOR]], typ='bool', pos=getpos(self.expr))
-        elif ltyp == 'int128' and rtyp == 'decimal':
-            return LLLnode.from_list([op, ['mul', left, DECIMAL_DIVISOR], right], typ='bool', pos=getpos(self.expr))
         else:
-            raise TypeMismatchException("Unsupported types for comparison: %r %r" % (ltyp, rtyp), self.expr)
+            raise TypeMismatchException("Unsupported types for comparison: %r %r" % (left_type, right_type), self.expr)
 
     def boolean_operations(self):
         if len(self.expr.values) != 2:


Test patch:
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
@@ -27,7 +27,7 @@ def log(n: int128) -> int128:
     c: decimal = n * 1.0
     output: int128 = 0
     for i in range(40):
-        if c < 10:
+        if c < 10.0:
             output = i * 10
             break
         c = c / 10
@@ -55,13 +55,13 @@ def log(n: int128) -> int128:
     c: decimal = convert(n, 'decimal')
     output: int128 = 0
     for i in range(40):
-        if c < 10:
+        if c < 10.0:
             output = i * 10
             break
         c /= 10
     for i in range(10):
         c /= 1.2589
-        if c < 1:
+        if c < 1.0:
             output = output + i
             break
     return output
diff --git a/tests/parser/syntax/test_bool.py b/tests/parser/syntax/test_bool.py
--- a/tests/parser/syntax/test_bool.py
+++ b/tests/parser/syntax/test_bool.py
@@ -32,6 +32,17 @@ def foo() -> bool:
 @public
 def foo() -> bool:
     return (1 == 2) or 3
+    """,
+    """
+@public
+def foo() -> bool:
+    return 1.0 == 1
+    """,
+    """
+@public
+def foo() -> bool:
+    a: address
+    return a == 1
     """
 ]
 
@@ -84,7 +95,7 @@ def foo() -> bool:
     """
 @public
 def foo() -> bool:
-    return 1. >= 1
+    return 2 >= 1
     """,
     """
 @public
@@ -94,7 +105,7 @@ def foo() -> bool:
     """
 @public
 def foo() -> bool:
-    return 1 <= 1.
+    return 1 <= 1
     """
 ]