-
-
Notifications
You must be signed in to change notification settings - Fork 796
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat[lang]: allow module intrinsic interface call #4090
base: master
Are you sure you want to change the base?
feat[lang]: allow module intrinsic interface call #4090
Conversation
allow `module.__interface__` to be used in call position by adding it to the module membership data structure. additionally, fix a bug where interfaces defined inline could not be exported. this is simultaneously fixed as a related bug because previously, interfaces could come up in export analysis as `InterfaceT` or `TYPE_T` depending on their provenance. this commit fixes the bug by making them `TYPE_T` in both imported and inlined provenance. refactor: - wrap interfaces in TYPE_T - streamline an `isinstance(t, (VyperType, TYPE_T))` check. `TYPE_T` now inherits from `VyperType`, so it doesn't need to be listed separately
there was a test for unimplemented `.vyi` interfaces, this commit adds a test for unimplemented inline interface for completeness
we allow for exporting a module with no external functions - i think we should raise in such case: # main.vy
import lib1
def f(x: Bytes[32*5]) -> uint256:
k: uint256 = lib1.foo()
return k
exports: lib1.__interface__
# lib1.vy
@internal
def foo() -> uint256:
return 1 |
import lib1
uses: lib1
@deploy
def __init__():
lib1.__interface__(self).__init__()
exports: lib1.__interface__
#lib1.vy
k: uint256
@external
def bar():
pass
@deploy
def __init__():
self.k = 10
|
main.vy
import lib1
#uses: lib1
@deploy
def __init__():
log lib1.__interface__.Foo(1)
s: lib1.Structt = lib1.__interface__.Structt(i=1)
exports: lib1.__interface__
#lib1.vy
event Foo:
i: uint256
struct Structt:
i: uint256
k: uint256
@external
def bar():
pass
@deploy
def __init__():
self.k = 10 |
should address #3943, right? |
with
# main.vy
import lib1
@external
def foo() -> uint256:
return staticcall lib1.__interface__(self).d()
# lib1.vy
d: public(uint256) |
would it be too much to ask for implicit cast of
|
on latest (9621397) we get:
|
yes but it's a bit hairy. it will feel ambiguous once we add |
|
yes. updated the PR description |
should be fixed as of latest (24ac428) |
i'm not too bothered. it looks a bit weird, but technically |
it was only there for `-f abi` output -- since it is a standards requirement to have the constructor in the abi output, but it doesn't semantically make sense in-language for the init function to be the interface, we add it back in later, at abi generation time. add a test that `module.__interface__(...).__init__()` is not allowed.
a bit oos for this PR, but we allow for |
for code like # main.vy
import lib1
implements: lib1. __interface__ i get:
which is weird given we allow # main.vy
import lib1
exports: lib1. __interface__ EDIT: i must have made a mistake during branch switching - i was cross-checking the behavior also against master and I can't repro this against this branch |
# main.vy
import ITest2
exports: ITest2
# ITest2.vyi
def foo() -> uint8:
...
@view
def foobar() -> uint8:
... yields:
EDIT: i must have made a mistake during branch switching - i was cross-checking the behavior also against master and I can't repro this against this branch |
yes, that was the original intention however, as i test it, the poc now doesn't work. is this intentional? |
i can't reproduce this. can you provide the contents you have for |
i can't reproduce this. when i run this i get the error:
|
|
you can call # main.vy
import lib2
@external
def bar():
extcall lib2.__interface__(self).__default__()
# lib2.vy
@external
def __default__():
pass i think you wanna be able to export it but not call it |
exports of the following form are allowed: # main.vy
import lib2
a: address
exports: lib2.__interface__(self.a).__default__
# lib2.vy
@external
def __default__():
pass
|
also add a test for an exception case that was not tested before
|
been thinking about this more and maybe it's feasible? since we already guard external calls with x: Mod = deploy Mod(args...)
^^^ ^^^
type: interface
type: module ctor
extcall Mod(addr)
^^^
type: interface it will be kind of confusing to have |
another fun alternative that is slightly less verbose is:
|
allow
module.__interface__
to be used in call position by adding it to the module membership data structure.additionally, fix a bug where interfaces defined inline could not be exported. this is simultaneously fixed as a related bug because previously, interfaces could come up in export analysis as
InterfaceT
orTYPE_T
depending on their provenance. this commit fixes the bug by making themTYPE_T
in both imported and inlined provenance.refactor:
isinstance(t, (VyperType, TYPE_T))
check.TYPE_T
now inherits fromVyperType
, so it doesn't need to be listed separatelyWhat I did
fixes #3943
How I did it
How to verify it
Commit message
Commit message for the final, squashed PR. (Optional, but reviewers will appreciate it! Please see our commit message style guide for what we would ideally like to see in a commit message.)
Description for the changelog
Cute Animal Picture