-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
generally disallow recursive structural types, check proc param types #24893
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
Conversation
Definitely improves the situation but for the future we should remove the restriction that recursive types must go through a nominal type and instead simply accept these definitions and make sigmatch etc check for endless recursions. |
Thanks for your hard work on this PR! Hint: mm: orc; opt: speed; options: -d:release |
…#24893) fixes #5631, fixes #8938, fixes #18855, fixes #19271, fixes #23885, fixes #24877 `isTupleRecursive`, previously only called to give an error for illegal recursions for: * tuple fields * types declared in type sections * explicitly instantiated generic types did not check for recursions in proc types. It now does, meaning proc types now need a nominal type layer to recurse over themselves. It is renamed to `isRecursiveStructuralType` to better reflect what it does, it is different from a recursive type that cannot exist due to a lack of pointer indirection which is possible for nominal types. It is now also called to check the param/return types of procs, similar to how tuple field types are checked. Pointer indirection checks are not needed since procs are pointers. I wondered if this would lead to a slowdown in the compiler but since it only skips structural types it shouldn't take too many iterations, not to mention only proc types are newly considered and aren't that common. But maybe something in the implementation could be inefficient, like the cycle detector using an IntSet. Note: The name `isRecursiveStructuralType` is not exactly correct because it still checks for `distinct` types. If it didn't, then the compiler would accept this: ```nim type A = distinct B B = ref A ``` But this breaks when attempting to write `var x: A`. However this is not the case for: ```nim type A = object x: B B = ref A ``` So a better description would be "types that are structural on the backend". A future step to deal with #14015 and #23224 might be to check the arguments of `tyGenericInst` as well but I don't know if this makes perfect sense. (cherry picked from commit 7f0e074)
fixes #5631, fixes #8938, fixes #18855, fixes #19271, fixes #23885, fixes #24877
isTupleRecursive
, previously only called to give an error for illegal recursions for:did not check for recursions in proc types. It now does, meaning proc types now need a nominal type layer to recurse over themselves. It is renamed to
isRecursiveStructuralType
to better reflect what it does, it is different from a recursive type that cannot exist due to a lack of pointer indirection which is possible for nominal types.It is now also called to check the param/return types of procs, similar to how tuple field types are checked. Pointer indirection checks are not needed since procs are pointers.
I wondered if this would lead to a slowdown in the compiler but since it only skips structural types it shouldn't take too many iterations, not to mention only proc types are newly considered and aren't that common. But maybe something in the implementation could be inefficient, like the cycle detector using an IntSet.
Note: The name
isRecursiveStructuralType
is not exactly correct because it still checks fordistinct
types. If it didn't, then the compiler would accept this:But this breaks when attempting to write
var x: A
. However this is not the case for:So a better description would be "types that are structural on the backend".
A future step to deal with #14015 and #23224 might be to check the arguments of
tyGenericInst
as well but I don't know if this makes perfect sense.