Skip to content

Commit

Permalink
fix: fix super() usage in multiple inheritance scenarios
Browse files Browse the repository at this point in the history
---------

note that this has been fixed over multiple previous commits, almost incidentally as part of the puyapy/puya split, this commit just adds tests that confirm the fix
  • Loading branch information
achidlow committed Aug 30, 2024
1 parent 62b9064 commit 49db7ae
Show file tree
Hide file tree
Showing 69 changed files with 5,639 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/sizes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
constants/ByteConstants 92 76 16 76 0
contains 1702 1627 75 1627 0
control_op_simplification 48 44 4 38 6
diamond_mro/Base1 176 156 20 156 0
diamond_mro/Base2 176 156 20 156 0
diamond_mro/Derived 272 252 20 252 0
diamond_mro/GP 130 110 20 110 0
dup2_optimization_bug 30 22 8 22 0
edverify/Verify 40 26 14 26 0
enumeration/Enumeration 523 479 44 479 0
Expand Down
Empty file.
14 changes: 14 additions & 0 deletions test_cases/diamond_mro/base1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from algopy import arc4, log

from test_cases.diamond_mro.gp import GP


class Base1(GP):
def __init__(self) -> None:
log("base1.__init__")
super().__init__()

@arc4.abimethod
def method(self) -> None:
log("base1.method")
super().method()
14 changes: 14 additions & 0 deletions test_cases/diamond_mro/base2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from algopy import arc4, log

from test_cases.diamond_mro.gp import GP


class Base2(GP):
def __init__(self) -> None:
log("base2.__init__")
super().__init__()

@arc4.abimethod
def method(self) -> None:
log("base2.method")
super().method()
15 changes: 15 additions & 0 deletions test_cases/diamond_mro/derived.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from algopy import arc4, log

from test_cases.diamond_mro.base1 import Base1
from test_cases.diamond_mro.base2 import Base2


class Derived(Base1, Base2):
def __init__(self) -> None:
log("derived.__init__")
super().__init__()

@arc4.abimethod
def method(self) -> None:
log("derived.method")
super().method()
17 changes: 17 additions & 0 deletions test_cases/diamond_mro/gp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import abc

from algopy import ARC4Contract, arc4, log


class GP(ARC4Contract, abc.ABC):
def __init__(self) -> None:
log("gp.__init__")
super().__init__()

@arc4.abimethod(create="require")
def create(self) -> None:
pass

@arc4.abimethod
def method(self) -> None:
log("gp.method")
124 changes: 124 additions & 0 deletions test_cases/diamond_mro/out/Base1.approval.mir

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions test_cases/diamond_mro/out/Base1.approval.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#pragma version 10

test_cases.diamond_mro.base1.Base1.approval_program:
txn ApplicationID
bnz main_entrypoint@2
callsub __init__

main_entrypoint@2:
callsub __puya_arc4_router__
return


// test_cases.diamond_mro.base1.Base1.__puya_arc4_router__() -> uint64:
__puya_arc4_router__:
// diamond_mro/base1.py:6
// class Base1(GP):
proto 0 1
txn NumAppArgs
bz __puya_arc4_router___after_if_else@7
method "method()void"
method "create()void"
txna ApplicationArgs 0
match __puya_arc4_router___method_route@2 __puya_arc4_router___create_route@3
int 0
retsub

__puya_arc4_router___method_route@2:
// diamond_mro/base1.py:11
// @arc4.abimethod
txn OnCompletion
!
assert // OnCompletion is NoOp
txn ApplicationID
assert // is not creating
callsub method
int 1
retsub

__puya_arc4_router___create_route@3:
// diamond_mro/gp.py:11
// @arc4.abimethod(create="require")
txn OnCompletion
!
assert // OnCompletion is NoOp
txn ApplicationID
!
assert // is creating
int 1
retsub

__puya_arc4_router___after_if_else@7:
// diamond_mro/base1.py:6
// class Base1(GP):
int 0
retsub


// test_cases.diamond_mro.base1.Base1.method() -> void:
method:
// diamond_mro/base1.py:11-12
// @arc4.abimethod
// def method(self) -> None:
proto 0 0
// diamond_mro/base1.py:13
// log("base1.method")
byte "base1.method"
log
// diamond_mro/base1.py:14
// super().method()
callsub test_cases.diamond_mro.gp.GP.method
retsub


// test_cases.diamond_mro.gp.GP.method() -> void:
test_cases.diamond_mro.gp.GP.method:
// diamond_mro/gp.py:15-16
// @arc4.abimethod
// def method(self) -> None:
proto 0 0
// diamond_mro/gp.py:17
// log("gp.method")
byte "gp.method"
log
retsub


// test_cases.diamond_mro.base1.Base1.__init__() -> void:
__init__:
// diamond_mro/base1.py:7
// def __init__(self) -> None:
proto 0 0
// diamond_mro/base1.py:8
// log("base1.__init__")
byte "base1.__init__"
log
// diamond_mro/base1.py:9
// super().__init__()
callsub test_cases.diamond_mro.gp.GP.__init__
retsub


// test_cases.diamond_mro.gp.GP.__init__() -> void:
test_cases.diamond_mro.gp.GP.__init__:
// diamond_mro/gp.py:7
// def __init__(self) -> None:
proto 0 0
// diamond_mro/gp.py:8
// log("gp.__init__")
byte "gp.__init__"
log
retsub
61 changes: 61 additions & 0 deletions test_cases/diamond_mro/out/Base1.arc32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"hints": {
"method()void": {
"call_config": {
"no_op": "CALL"
}
},
"create()void": {
"call_config": {
"no_op": "CREATE"
}
}
},
"source": {
"approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLmRpYW1vbmRfbXJvLmJhc2UxLkJhc2UxLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIGNhbGxzdWIgX19wdXlhX2FyYzRfcm91dGVyX18KICAgIHJldHVybgoKCi8vIHRlc3RfY2FzZXMuZGlhbW9uZF9tcm8uYmFzZTEuQmFzZTEuX19wdXlhX2FyYzRfcm91dGVyX18oKSAtPiB1aW50NjQ6Cl9fcHV5YV9hcmM0X3JvdXRlcl9fOgogICAgLy8gZGlhbW9uZF9tcm8vYmFzZTEucHk6NgogICAgLy8gY2xhc3MgQmFzZTEoR1ApOgogICAgcHJvdG8gMCAxCiAgICB0eG4gTnVtQXBwQXJncwogICAgYnogX19wdXlhX2FyYzRfcm91dGVyX19fYWZ0ZXJfaWZfZWxzZUA3CiAgICBtZXRob2QgIm1ldGhvZCgpdm9pZCIKICAgIG1ldGhvZCAiY3JlYXRlKCl2b2lkIgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAogICAgbWF0Y2ggX19wdXlhX2FyYzRfcm91dGVyX19fbWV0aG9kX3JvdXRlQDIgX19wdXlhX2FyYzRfcm91dGVyX19fY3JlYXRlX3JvdXRlQDMKICAgIGludCAwCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX21ldGhvZF9yb3V0ZUAyOgogICAgLy8gZGlhbW9uZF9tcm8vYmFzZTEucHk6MTEKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiBtZXRob2QKICAgIGludCAxCiAgICByZXRzdWIKCl9fcHV5YV9hcmM0X3JvdXRlcl9fX2NyZWF0ZV9yb3V0ZUAzOgogICAgLy8gZGlhbW9uZF9tcm8vZ3AucHk6MTEKICAgIC8vIEBhcmM0LmFiaW1ldGhvZChjcmVhdGU9InJlcXVpcmUiKQogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgIQogICAgYXNzZXJ0IC8vIGlzIGNyZWF0aW5nCiAgICBpbnQgMQogICAgcmV0c3ViCgpfX3B1eWFfYXJjNF9yb3V0ZXJfX19hZnRlcl9pZl9lbHNlQDc6CiAgICAvLyBkaWFtb25kX21yby9iYXNlMS5weTo2CiAgICAvLyBjbGFzcyBCYXNlMShHUCk6CiAgICBpbnQgMAogICAgcmV0c3ViCgoKLy8gdGVzdF9jYXNlcy5kaWFtb25kX21yby5iYXNlMS5CYXNlMS5tZXRob2QoKSAtPiB2b2lkOgptZXRob2Q6CiAgICAvLyBkaWFtb25kX21yby9iYXNlMS5weToxMS0xMgogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICAvLyBkZWYgbWV0aG9kKHNlbGYpIC0+IE5vbmU6CiAgICBwcm90byAwIDAKICAgIC8vIGRpYW1vbmRfbXJvL2Jhc2UxLnB5OjEzCiAgICAvLyBsb2coImJhc2UxLm1ldGhvZCIpCiAgICBieXRlICJiYXNlMS5tZXRob2QiCiAgICBsb2cKICAgIC8vIGRpYW1vbmRfbXJvL2Jhc2UxLnB5OjE0CiAgICAvLyBzdXBlcigpLm1ldGhvZCgpCiAgICBjYWxsc3ViIHRlc3RfY2FzZXMuZGlhbW9uZF9tcm8uZ3AuR1AubWV0aG9kCiAgICByZXRzdWIKCgovLyB0ZXN0X2Nhc2VzLmRpYW1vbmRfbXJvLmdwLkdQLm1ldGhvZCgpIC0+IHZvaWQ6CnRlc3RfY2FzZXMuZGlhbW9uZF9tcm8uZ3AuR1AubWV0aG9kOgogICAgLy8gZGlhbW9uZF9tcm8vZ3AucHk6MTUtMTYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgLy8gZGVmIG1ldGhvZChzZWxmKSAtPiBOb25lOgogICAgcHJvdG8gMCAwCiAgICAvLyBkaWFtb25kX21yby9ncC5weToxNwogICAgLy8gbG9nKCJncC5tZXRob2QiKQogICAgYnl0ZSAiZ3AubWV0aG9kIgogICAgbG9nCiAgICByZXRzdWIKCgovLyB0ZXN0X2Nhc2VzLmRpYW1vbmRfbXJvLmJhc2UxLkJhc2UxLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBkaWFtb25kX21yby9iYXNlMS5weTo3CiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gZGlhbW9uZF9tcm8vYmFzZTEucHk6OAogICAgLy8gbG9nKCJiYXNlMS5fX2luaXRfXyIpCiAgICBieXRlICJiYXNlMS5fX2luaXRfXyIKICAgIGxvZwogICAgLy8gZGlhbW9uZF9tcm8vYmFzZTEucHk6OQogICAgLy8gc3VwZXIoKS5fX2luaXRfXygpCiAgICBjYWxsc3ViIHRlc3RfY2FzZXMuZGlhbW9uZF9tcm8uZ3AuR1AuX19pbml0X18KICAgIHJldHN1YgoKCi8vIHRlc3RfY2FzZXMuZGlhbW9uZF9tcm8uZ3AuR1AuX19pbml0X18oKSAtPiB2b2lkOgp0ZXN0X2Nhc2VzLmRpYW1vbmRfbXJvLmdwLkdQLl9faW5pdF9fOgogICAgLy8gZGlhbW9uZF9tcm8vZ3AucHk6NwogICAgLy8gZGVmIF9faW5pdF9fKHNlbGYpIC0+IE5vbmU6CiAgICBwcm90byAwIDAKICAgIC8vIGRpYW1vbmRfbXJvL2dwLnB5OjgKICAgIC8vIGxvZygiZ3AuX19pbml0X18iKQogICAgYnl0ZSAiZ3AuX19pbml0X18iCiAgICBsb2cKICAgIHJldHN1Ygo=",
"clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgp0ZXN0X2Nhc2VzLmRpYW1vbmRfbXJvLmJhc2UxLkJhc2UxLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICBpbnQgMQogICAgcmV0dXJuCg=="
},
"state": {
"global": {
"num_byte_slices": 0,
"num_uints": 0
},
"local": {
"num_byte_slices": 0,
"num_uints": 0
}
},
"schema": {
"global": {
"declared": {},
"reserved": {}
},
"local": {
"declared": {},
"reserved": {}
}
},
"contract": {
"name": "Base1",
"methods": [
{
"name": "method",
"args": [],
"readonly": false,
"returns": {
"type": "void"
}
},
{
"name": "create",
"args": [],
"readonly": false,
"returns": {
"type": "void"
}
}
],
"networks": {}
},
"bare_call_config": {}
}
9 changes: 9 additions & 0 deletions test_cases/diamond_mro/out/Base1.clear.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Op // Stack (out)

#pragma version 10

// test_cases.diamond_mro.base1.Base1.clear_state_program() -> uint64:
main_block@0:
int 1 // 1
return //

5 changes: 5 additions & 0 deletions test_cases/diamond_mro/out/Base1.clear.teal
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma version 10

test_cases.diamond_mro.base1.Base1.clear_state_program:
int 1
return
65 changes: 65 additions & 0 deletions test_cases/diamond_mro/out/Base1.destructured.ir
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
contract test_cases.diamond_mro.base1.Base1:
program approval:
subroutine algopy.arc4.ARC4Contract.approval_program() -> bool:
block@0: // L-1
let app_id%0#0: uint64 = (txn ApplicationID)
goto app_id%0#0 ? block@2 : block@1
block@1: // on_create_L7
test_cases.diamond_mro.base1.Base1.__init__()
goto block@2
block@2: // entrypoint_L7
let tmp%0#0: bool = test_cases.diamond_mro.base1.Base1.__puya_arc4_router__()
return tmp%0#0

subroutine test_cases.diamond_mro.base1.Base1.__puya_arc4_router__() -> bool:
block@0: // L6
let tmp%0#0: uint64 = (txn NumAppArgs)
goto tmp%0#0 ? block@1 : block@7
block@1: // abi_routing_L6
let tmp%2#0: bytes = (txna ApplicationArgs 0)
switch tmp%2#0 {method "method()void" => block@2, method "create()void" => block@3, * => return 0u}
block@2: // method_route_L11
let tmp%3#0: uint64 = (txn OnCompletion)
let tmp%4#0: bool = (! tmp%3#0)
(assert tmp%4#0) // OnCompletion is NoOp
let tmp%5#0: uint64 = (txn ApplicationID)
(assert tmp%5#0) // is not creating
test_cases.diamond_mro.base1.Base1.method()
return 1u
block@3: // create_route_L11
let tmp%7#0: uint64 = (txn OnCompletion)
let tmp%8#0: bool = (! tmp%7#0)
(assert tmp%8#0) // OnCompletion is NoOp
let tmp%9#0: uint64 = (txn ApplicationID)
let tmp%10#0: bool = (! tmp%9#0)
(assert tmp%10#0) // is creating
return 1u
block@7: // after_if_else_L6
return 0u

subroutine test_cases.diamond_mro.base1.Base1.method() -> void:
block@0: // L11
(log "base1.method")
test_cases.diamond_mro.gp.GP.method()
return

subroutine test_cases.diamond_mro.gp.GP.method() -> void:
block@0: // L15
(log "gp.method")
return

subroutine test_cases.diamond_mro.base1.Base1.__init__() -> void:
block@0: // L7
(log "base1.__init__")
test_cases.diamond_mro.gp.GP.__init__()
return

subroutine test_cases.diamond_mro.gp.GP.__init__() -> void:
block@0: // L7
(log "gp.__init__")
return

program clear-state:
subroutine algopy.arc4.ARC4Contract.clear_state_program() -> bool:
block@0: // L-1
return 1u
Loading

0 comments on commit 49db7ae

Please sign in to comment.