-
Notifications
You must be signed in to change notification settings - Fork 74
Inefficiency with (Unbounded) Parameteric Polymorphism #117
Comments
I would assume that the nature of memoization is that it is always constructed incrementally while checking. That seems unavoidable with polymorphism. What alternative do you have in mind?
Once you have type parameters, a structural component to subtyping is inherent and unavoidable. You have to traverse the type parameters structurally, and they can be arbitrarily nested. Checking whether I suppose what you are getting at is that there is an expansion involved if Pair is an alias instead of a nominal definition. And that this expansion involves (at least conceptually) substitution. That is correct, but a separate issue. More importantly, this is already the case for link-time type checking, even with nominal definitions. So a Wasm engine has to implement (or emulate) structural substitution and incremental memoization no matter what. AFAICS, the extension does not change the worst-case complexity of type checking. You could expand all type instantiations in a linear pre-pass before checking. But of course, type polymorphism allows expressing much bigger types. In practice, I would probably not perform actual substitution, but rather run the subtyping check relative to a local substitution environment. |
This linear pre-pass is only useful for memoization if you recognize redundancies across instantiations. That requires hash-consing, which is linear with respect to the size of the type. In other words, memoization itself becomes linear time rather than constant time. Furthermore, you have to use a hashmap rather than an array to implement memoization, which causes its own slowdowns. There's also the important issue that grammatically identical types are not necessarily identical in the presence of bounded parametric polymorphism (even only predicative polymorphism, which is decidable). The same type variable can have different bounds in different environments. This makes defining/implementing the cons-hashing function more complicated/expensive, and it reduces the number of redundancies.
Actually, memoization is only useful if there are lots of redundancies, there is an easy way to identify redundancies, and the operation being memoized is slow. But well-designed subtyping systems are linear time except for corner cases, and implementable without any data structures (besides the type expression), whereas memoization itself is already linear time and requires maintaining a hashmap and is sensitive to loss in redundancies. This makes a difference in practice. I've even seen removing memoization speed up type-checking by over an order of magnitude. That, of course, relied on non-memoized subtyping being efficient, which isn't the case with this proposal.
Your second sentence here captures why the comparison in your first sentence here is completely misrepresentative of the issues. Remember that the nominal type for
The nominal type |
The type system for the MVP is now settled, but of course will have to make sure that any post-MVP features we work on have appropriate algorithmic complexity. PRs adding general notes about known algorithmic issues to the post-MVP doc would be welcome, but I'll close this particular issue since it's not actionable for this particular proposal. |
Terminology note: Parametric polymorphism is the use of instantiable type parameters, whereas subtype polymorphism is the use of subtyping.
In #114, the following extensions are described as part of a sketch for supporting parametric polymorphism (where I've removed bounds):
This extension makes subtyping at least quadratic time and no longer amortizable with memoization. The ability to instantiate type parameters with type arguments means new types are constructed during type checking and consequently have no entries in a memoization table.
This inefficiency in the presence of parametric polymorphism seems fundamental to the use of structural types in the current MVP.
The text was updated successfully, but these errors were encountered: