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
Problem Function References and Name Mangling #554
Comments
So, if we display the mangles as generated by GOT: function(sum1:Sized) -> int MANGLE: getSized$Z9bFaA$WL13$n0FS$o5$lJ$B4$d0VT$J5$Zx ... GOT: X<function({X getSize,int size,...}) -> int> MANGLE: getSized$Z9bFaA$WE9FJD$D2Vm$VD$a1Vo$FE$9Y$ND$H2$x$cgz ... We can see clearly that it's not generated the same name mangles. In fact, the interesting thing here is that the problem is arising because one type is "raw" and the other contains a "nominal". Interesting... |
UPDATE: so the first mangle is occurring at the definition site. |
So, thinking about this there are two options:
Seems like I prefer option (2) above because this retains as we generally prefer to retain as much nominal information as possible. I suppose I should add a test case or two. |
This test case was designed to illustrate the problem highlighted in this issue, however it is not actually achieving that. Rather, the problem does not show on the JVM but does show on the WyIL intepreter.
Have added test case The essential difference appears to be that the lambda is stored in a constant definition in the original example, where as in my new test case it's not. |
This illustrates the problem as identified in issue 554. Unlike FunctionRef_Valid_10, this illustrates the issue on the JVM as well.
Options 1 and 2 are interesting tradeoffs. I assume that raw type means base type, while nominal means the full subtype information. Z uses option 1 for typechecking (it just checks base types), but one must still use the richer type for reasoning. Keeping nominal types (full subtype information) might make it easier to support F-bounded quantification in the future, so that methods within subtypes can know that one of their inputs is the subtype rather than the supertype? This would be one step closer to supporting OOP. |
Hey Mark, Yeah, raw type means that we extract all nominal type information just leaving the "base" type. For example: type Point is { int x, int y } function f(Point p) -> int: ... The nominal type of function Yes, effectively, I use option (1) for type checking. Option (2) is retained for providing better debugging output, and also potentially to allow overloading of constrained types (though this is not really implemented yet). |
This illustrates the problem as identified in issue 554. Unlike FunctionRef_Valid_10, this illustrates the issue on the JVM as well.
The problem is an interesting one. Essentially, when a Later this single instance is turned back into an instance of // FIXME: loss of nominal information here, since the type of the // constant in question is always fully expanded. return Nominal.construct(value.type(), value.type()); Late the |
So, what are the options? Here are some:
Based on that, option (1) seems like the sensible though rather laborious approach. I wonder if there are other ways in which option (1) would benefit us? For example, it seems possible that there are other situations where the loss of nominal information could be a problem... |
Other options include:
|
it seems possible that there are other situations where the loss of nominal information could be a problem... Right, I'm not sure about this now. Basically it requires there to be a difference between the nominal and raw type for a constant. There aren't many situations where this could arise, since constants are generally by their very nature "raw" in some sense. It's only Lambda's that seem to bring in a non-raw type. If casts were allowed in constant expressions, then something like this might do it: type TRec is {int x, int y} constant CRec is (TRec) { x: 1, y: 2 } function f(TRec p) -> (int r): return p.x + p.y function g(int x) -> (int r): return f(CRec) Currently, this does not compile though. |
So, of course, the solution presents itself! The easiest thing is to have a proxy object to interface between the front-end AST and the WyIL which holds both types. And, we already have such an object: Expr.ConstantAccess ... |
This fix resolves a problem related to the nominal typing of lambda constants. The problem occurred because lambda constants were encoded as instances of wyil.lang.Constant which contained only one type slot. This contrasts with the expectation in FlowTypeChecker where we need both nominal and raw information. Previously, just raw information was used but this caused problems. Instead, we now propagate full Nominal information which resolves the issue.
Right, fixed. |
The following test case was show by @utting to fail at runtime:
The error message reported is:
In essence, this looks like a problem with name mangling...
The text was updated successfully, but these errors were encountered: