Polymorphism support #848
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "ghallak/307"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes: #307
I have noticed that the type for the function declaration
entrypoint init : () => unit
is:While the type of the function
entrypoint init() = ()
is:The function
aeso_ast_infer_types:unfold_types_in_type
replaces{id, _, "unit"}
with{tuple_t, _, []}
, but it does not seems to be called on thefun_t
type.@hanssv Do you know if this is a bug or if it's done on purpose?
Created by: hanssv
I have no recollection of it being done on purpose...
Created by: hanssv
I think we are soon approaching the point where this should become a record, something to consider for the next addition 😅
Created by: hanssv
This looks like an exponential blowup - we should consider a rewrite some day...
Created by: hanssv
Review: Dismissed
Looks good to me 👍
Created by: radrow
Review: Changes requested
I would like to see tests for:
contract Cat : Animal
:let f(x : Cat) : Animal = (g : Animal => Cat)
workslet f(x : Animal) : Animal = (g : Cat => Cat)
does not worklet f(x : Cat) : Cat = (g : Cat => Animal)
does not worklet f(x : Animal => Cat) : Animal = (g : (Cat => Animal) => Cat)
workslet f(x : Cat => Cat) : Animal = (g : (Animal => Animal) => Cat)
does not workCreated by: radrow
Also, please refer some runtime tests in aeternity repo, so we are sure nothing breaks there.
@hanssv @UlfNorell In the case of implementing two interfaces with entrypoints of the same name and same type
Do you think this should pass as a function called
f
with the type() => int
is already implemented? Or should it fail since only one of the interfaces is implemented, and not the other?I already have this test and it's failing, but I'm wondering if it should.
Created by: UlfNorell
I think the least error prone option is to not allow implementing interfaces with overlapping entrypoints. So in this case it should give an error already on
contract C : I, J =
. I don't see any great harm in allowing it though, so if there are convincing use cases where you want overlapping interfaces we could accept it.Created by: radrow
Do we have a test if C does not implement f?
Yes, contract_polymorphism_missing_implementation and it shows an error.
Created by: marc0olo
@ghallak I agree with Ulf, as long as there is no valid usecase to argue for we shouldn't allow implementing interfaces with overlapping entrypoints
Created by: radrow
I'd also modify some tests to involve tuples, maps, lists etc and custom types, so we are sure that subtyping works on them too
Created by: radrow
this could be a separate function imo
Created by: radrow
I guess?
Created by: radrow
This could be a
is_subtype/4
that callsis_subtype/3
, less indentationCreated by: radrow
Would you verify if it does not explode exponentially if you hack it?
Done here 7b5c9778b4f39dd6a96c1ea07d5978031ca90bc8
Done here cd3da44973ca25574079ae4f1c1a930c8828d6d6
Done here cd3da44973ca25574079ae4f1c1a930c8828d6d6
Created by: radrow
Why do you destroy and immediately create?
Created by: radrow
This check should go to a separate function imo
Created by: radrow
Move out
Created by: radrow
infer1
should read like a prose, otherwise we a growing a hydraCreated by: radrow
Function interfaces should be checked as well.
Created by: radrow
Add a test for that:
Created by: radrow
You can write
check_implemented_interfaces/4
that runs/5
with the accumulator. This is generally cleaner.Created by: radrow
Add a comment that you are solving the diamond problem here, it took me a while to get to this XD
Created by: radrow
Add comments on these functions, the name does not capture the point entirely and the logic is not super trivial
Created by: radrow
Empty lists don't match?
Created by: radrow
Var args are
Chain
exclusive and they should imo remain this way, so no need to worry about them. Regarding named args, you can just match them by name and typeCreated by: radrow
What is
compare_types
for? Why not just check for names (and maybe arity) and then rely on subtyping?Created by: radrow
What does it mean here?
Created by: radrow
I think you can just have a set for co and contra and then
Created by: radrow
I think it would be easier and simpler to use
infer_type_vars_variance
to dive into the type and just maintain an additional argument that tells what the current variance is. Then you won't need to count this.Created by: radrow
I need explanation on this, I totally don't get what's going on here. Also, why do you check only the result type and don't touch the args?
Created by: radrow
The error messages here could be more elaborate. I can already see people scratching their heads why Cat does not unify with Animal, but sometimes the other way around. I think it would be valuable to mention the variance in the message:
Or something. Even if one does not know the concept of variance, they know at least what to google.
Created by: radrow
Add tests for custom datatypes, records and type aliases. Please consider various variances. Also there should be tests for tuples, maps, lists and oracles.
Created by: radrow
Note that they serve for remote contracts as well!
Created by: radrow
I make this note here because I couldn't find any better place; what about builtin types such as option, oracle and oracle_query? How do you handle them?
Removing that was causing a failed test, but I've just found out that the failing test was failing because of another mistake that I've made.
Fixed here: 4790566f427a3f9ec01b41a61217a7fe319d2525
Done here 0a2e11e4e69b68ab10ee1f01e10b776172379664
Done here 0a2e11e4e69b68ab10ee1f01e10b776172379664
Done here 0a2e11e4e69b68ab10ee1f01e10b776172379664
Done here 0a2e11e4e69b68ab10ee1f01e10b776172379664
This is not solving the diamond problem, it's just there to recursively make sure that interfaces implemented by the interface in hand are also implemented by the contract.
Also, does the diamond problem happen in the case when implementing interfaces? Isn't it a problem with inheritance?
There is a comment in this commit
0a2e11e4e6
explaining what the function is doing.What is the point of duplicating the declaration of
f
in bothI0
andI1
when I'm already checking recursively thatC
is implementingI1
and all interfaces extended byI1
(onlyI0
in this case)?It's been a long time since I wrote this. I didn't know about
is_list/1
back then and thought this is the only way to check if a variable is a list.Fixed here: 55bc58286e224ab54fff62a3b8ae2cd0ca87adcb
Done here 62b095affc17a12ff634da242e212c51cbd36a99
Done here bdd3f0dde2f4423722808cdd5478a7a54d62f85f
Done here 39b9bb66cca29f836f8c36a3569df494dbd19aff
This is supposed to work in the case where the function is a type constructor. So it would work for something like:
where
f
is defined as:and
T
is a type constructor for the datatypetc
:In the above example, when trying to infer the type for
T(f)
, theFunType
forT(f)
would look something like:Note that
Ref
in the return type is the same as theRef
from the args, since the type above isdatatype tc('a) = TC('a => 'a)
, so it's enough to keep track of theRef
in the return type.Would it be better to say that
Animal
is not a subtype ofCat
instead of mentioning the variance part? Someone would scratch his head saying that why didn't the compiler check ifCat
is a subtype ofAnimal
instead of checking ifAnimal
is a subtype ofCat
, but people will always scratch their heads for some reason, and I don't see that mentioning the type of variance making it easier for people to find out what went wrong.I probably don't get the question.
Here we have access to the datatype's type variables
Xs
and the constructors for the datatypeCons
, and I use that to infer the type variance for these type variables.Are you asking about something else?
I don't think that
compare_types
is needed, that was meant to be a version ofunify
that does not give a type error (only returns true or false).If I use
unify
here instead ofcompare_types
, I will be getting 2 errors, onecannot_unify
error and anotherunimplemented_interface_function
where I only need the second one.I can modify
unify
to not give a type error in one of three ways:When
and use that to indicate that we don't need to throw an error in this case (Probably a bad idea since the valueWhen
is only used for output)Env
(e.g.unify_no_thorw
) and only throw if it's set totrue
unify
(e.g.ShouldThrow
) and only throw if it's set totrue
(That would cause changes in multiple lines of the code in each definition ofunify
)In the files
polymorphism_variance_switching.aes
andpolymorphism_variance_switching_custom_types.aes
there are tests for:I'll add to that tests for:
optionsoraclesoracle queriesrecordstype aliasesActually, I have faced the same issue while working on a different PR. I think that adding something like
unify_throws = true
to the recordenv
could be the best idea here.Created by: radrow
My point is to make it behave nicely when you use
I1
as an interface for a remote contract. Note that interfaces in Sophia are not abstract like in Java.Alternatively, the following code should work:
Created by: radrow
I think the previous name was better, this
_recursive
is mentioned in the comment anywayCreated by: radrow
Are you sure that named args are sorted at this point? If not, you will have false-negatives on this check.
Created by: radrow
What's wrong with unification errors here?
I just want to check whether two types are the same or not, and move on if they are not. Unification errors will stop the compilation, and I don't want that.
I have renamed it to
check_implemented_interfaces1
here 1e965681cb595dac95828b0f3d2680f89e96f5a1This is fixed now, check commits e74c75558b7a1fc5e48740f7f2f17ad7bbe2c76d and 831903e675091883688b43c1753aede892e4d8ab
I should probably rename all new test files to have a common prefix related to this PR before merging it.(I have done that heree4db742c72
)I have implemented that here 28bf14cc7cbda129dc7d4525e642b145698c1fea
I have tests for all the above now after 114010b8e1ff9a978912f736bd143364666bd89c, 8e995429aa6bd184b3d690f97dacf3ea6fb1b555, eab8eae9c1b97174fa93cb31201805aa45a4a578, and a6f1d8107713baa0379ecbacd06c1e51b4bd112c.
Done that here da6d22717cf3410b97792894aba371f353078ea1
Created by: radrow
what is
x
for here?Created by: radrow
Shouldn't
f0
callg0
?Created by: radrow
this test is duplicated in h0
Created by: radrow
I guess this is supposed to fail? Maybe make a note
Created by: radrow
this fails as well, right?
Created by: radrow
Would you make the names more descriptive? Don't have to be elaborate, but so it is not necessary to constantly lookup their defs
Created by: radrow
make names descriptive
Created by: radrow
missing bivariant
Created by: radrow
Imo oracle queries should be covariant on both positions:
Oracle.get_answer
Oracle.get_question
Created by: radrow
...and now I am happy that we don't have recursive datatypes
Done here 530940edd635da436cc737686f57b16f2f420009
Done here c767cd48a4c6399de89cd0eda9046fcd82e92f25
Created by: radrow
Please move this resolution to another function
Created by: radrow
Wait, is this really
('a => unit) => 'a
?! It should be parsed as'a => (unit => 'a)
what would make it invariant. Please check how it parsers and if it parses wrong then create issue to fix it. Also add parens so it is clear that it's('a => unit) => 'a
Created by: radrow
Or is it supposed to be invariant?
Created by: radrow
Same as above. Add parens.
Created by: radrow
In Haskell both 'a and 'b would be contra if you write it this way
Created by: radrow
write explicit types as I believe both
DT_BIV
would default args to units which is not what you test I guess.Created by: radrow
should pass
Created by: radrow
should pass
Created by: radrow
What does the rvalue type to?
dt_co_twice(Animal)
?Created by: radrow
But it should fail, just curious what's going on
Created by: radrow
I would also like to see the following scenario with some basic checks:
Created by: radrow
The trick is that the last 3 rvalues must not be inferred to be
Cat
. It should be eitherAnimal
or a type errorCreated by: radrow
Review: Approved
Created by: radrow
It's not perfect, but it's usable. We should consider improvements in the inference, but what is important now is:
Created by: hanssv
Review: Approved
Looks ok to me! Please squash before merging 😅
Merged by: ghallak at 2022-06-17 09:09:07 UTC