-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Fixed type variables in function definitions in experimental analysis #14606
Fixed type variables in function definitions in experimental analysis #14606
Conversation
Currently the PR breaks the Error: Cannot unify "b:type and 'k:type.
--> test/libsolidity/semanticTests/experimental/type_class.sol:10:5:
|
10 | function new() -> Self;
| ^^^^^^^^^^^^^^^^^^^^^^^ I think I need to replace the |
75b64e3
to
ecebed5
Compare
Problem with the type class variable solved by making it a fixed type variable. The remaining issue is that now this obviously won't unify with the concrete type used in the instantiation. I guess I have to do what I do for functions, that is, turn it into a generic variable before unification. The only complication is that it has to be a specific generic variable - the same one that was used to replace type class variable used in function definitions of that class. |
099a683
to
8b57e57
Compare
e86a606
to
bde0288
Compare
@@ -199,6 +200,82 @@ FixedTypeVariable TypeSystem::freshFixedTypeVariable(Sort _sort) | |||
return freshFixedVariable(_sort); | |||
} | |||
|
|||
experimental::Type TypeSystem::fixTypeVariables(Type const& _type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will work like done here - we will have to use unification as base mechanism here, i.e. recursively traverse the type and whenever we see a generic type variable create a new fixed one and unify (if you continue to resolve properly, unification will actually make the genericToFixed
map obsolete...
If we don't do that, the function body during code generation will have generic type variables for which we cannot tell what they mean in relation to the function type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reverse this will also be a bit of a headache - for that we'll need to use the concrete monomorphic function type and construct a substitution from fixed variables to instances to be used for codegen - but we can cross that bridge when we come to it, I expect this will mean a new kind of type environment that allows also tracking substitutions of fixed type variables not only generic ones to be used only in codegen (respectively for monomorphization)
Reading the PR and thinking through more implications for codegen, I actually increasingly think that it may be the better choice to just mark type variables as fixed in the type environment after all - we should talk about that. |
ecebed5
to
55366c0
Compare
instantiation T(A: P1): + { | ||
// FIXME: Type comparison with type class function fails because we get | ||
// two different variables for A. | ||
function add(x: T(A), y: T(A)) -> T(A) {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where I stopped last week. The comparison between function type in the instantiation and the type in the class (after substitution) fails because type T(A)
has a different type variable in each of these cases. The function from the instantiation has a fixed variable (like all function definitions now) while the type we substitute into the function from the class comes from instantiation header and is generalized.
@ekpyron I just pushed a cleaned up current state of the PR. Some of the other stuff I had in my branch went into #14635 and trivial stuff as fixups into #14510. So currently I need to solve this problem with the type variable in polymorphic types ending up generalized and failing function type comparison when I'm processing instantiations. Then replace |
By now, I'm quite convinced that the current attempt of introducing We should, instead, add a set of fixed type variables to That means, that type checking a function can remain exactly the same as before, just at the end of the function you fix the types, by just adding the type variables involved in the function's signature to the set of fixed type variables in the global Then generalizing also remains fully identical to the current And whenever you want to temporarily unify anything that is fixed (for example for unification during code generation) you can just create a new |
Conversely, if you want to declare a fixed type variable, you can just introduce them as the one-and-the-same-kind of It's a bit unfortunate that we spent some time on the other approach of introducing a completely separate kind of type variable, but that's normal for working on experimental stuff and moving the distinction to the |
ok then. I'll put this PR on hold and switch to the approach with the type environment. I think we'll still benefit from the time I spent on this because a lot of it went into trying to understand how things work and also getting some relevant tests that will tell me when I'm breaking something that's supposed to already work. So it should be quicker this time. |
2ab295f
to
781a73b
Compare
Closing in favor of #14606. |
Part of #14570.
Depends on #14635.
The PR introduces fixed free type variables and implements unification for them. Then replaces generic variables with fixed ones in a function definition once it's processed. It does not yet use fixed type variables for anything else.