Repository: vyperlang/vyper

Issue:
Types not enforced on tuple return - bug
Attempting to compile:
```python
@public
def getTime() -> uint256:
    return block.timestamp
```
rightfully returns the error 
```
vyper.exceptions.TypeMismatchException: line 3: 
Return type units mismatch uint256(sec, positional) uint256
```

However, this compiles just fine:
```python
@public
def getTimeAndBalance() -> (bool, address):
    return block.timestamp, self.balance
```
Types not enforced on tuple return - bug
Attempting to compile:
```python
@public
def getTime() -> uint256:
    return block.timestamp
```
rightfully returns the error 
```
vyper.exceptions.TypeMismatchException: line 3: 
Return type units mismatch uint256(sec, positional) uint256
```

However, this compiles just fine:
```python
@public
def getTimeAndBalance() -> (bool, address):
    return block.timestamp, self.balance
```


Discussion:
LOL that's properly effed up
Vyper: "hold on there, don't go mixing your seconds with your unsigned integers"

Also Vyper: "yup, you can stick that bovine into that cactus-shaped hole if you just add a stick of butter, no problem"
What's more effed up is that I actually read the check for this commented out in the code... meaning I must've done it midway through some other PR. And there is no test for it. https://github.com/ethereum/vyper/blob/eda157559d9585dad936a0829806967a0beb60b1/vyper/parser/parser.py#L847
LOL that's properly effed up
Vyper: "hold on there, don't go mixing your seconds with your unsigned integers"

Also Vyper: "yup, you can stick that bovine into that cactus-shaped hole if you just add a stick of butter, no problem"
What's more effed up is that I actually read the check for this commented out in the code... meaning I must've done it midway through some other PR. And there is no test for it. https://github.com/ethereum/vyper/blob/eda157559d9585dad936a0829806967a0beb60b1/vyper/parser/parser.py#L847

Resolving patch:
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
@@ -635,7 +635,10 @@ def increment_dynamic_offset(dynamic_spot):
                 ['mload', dynamic_offset_counter]]
         ]
 
-    items = sub.typ.tuple_items()
+    if not isinstance(context.return_type, TupleLike):
+        raise TypeMismatchException('Trying to return %r when expecting %r' % (sub.typ, context.return_type), getpos(stmt))
+    items = context.return_type.tuple_items()
+
     dynamic_offset_start = 32 * len(items)  # The static list of args end.
 
     for i, (key, typ) in enumerate(items):


Test patch:
diff --git a/tests/parser/functions/test_return_tuple.py b/tests/parser/functions/test_return_tuple.py
--- a/tests/parser/functions/test_return_tuple.py
+++ b/tests/parser/functions/test_return_tuple.py
@@ -1,3 +1,6 @@
+from vyper.exceptions import TypeMismatchException
+
+
 def test_return_type(get_contract_with_gas_estimation):
     long_string = 35 * "test"
 
@@ -113,3 +116,13 @@ def test() -> (int128, bytes[20], address, bytes[20]):
     c = get_contract_with_gas_estimation(code)
 
     assert c.out_literals() == [1, b"testtesttest", None, b"random"]
+
+
+def test_tuple_return_typecheck(assert_tx_failed, get_contract_with_gas_estimation):
+    code = """
+@public
+def getTimeAndBalance() -> (bool, address):
+    return block.timestamp, self.balance
+    """
+
+    assert_tx_failed(lambda: get_contract_with_gas_estimation(code), TypeMismatchException)