bind generic param/or to constraint for conversion match#24250
bind generic param/or to constraint for conversion match#24250metagn wants to merge 1 commit intonim-lang:develfrom
or to constraint for conversion match#24250Conversation
fixes nim-lang#4858, fixes nim-lang#10027, fixes nim-lang#12552, fixes nim-lang#15721, fixes nim-lang#21331, refs nim-lang#1214, follows up nim-lang#24216, split from nim-lang#24198
To me this implies that the |
I was only guessing the reason for that behavior, I just figured it was a consequence of Nim's bind-once behavior in general, as evidenced by the test in bf4ce87 where it was added. The bindings are still bound to the IDs regardless, we would need to guarantee that every typeclass inside a generic constraint has a copied ID and maybe these copied IDs would even have to be equal for the same types in the same generic constraint if we want to keep some of the bind-once behavior. The guarantee of "nothing bound in this context except generic parameters will matter" seems easier to maintain than "every use of a typeclass will have its own ID". Arguably the only things that should ever bind are generic parameters but no binding for the |
|
Another issue popped up that I think has a similar solution: #24337 It points out a small issue in this PR though: the I'm not sure if a first version of the check for "generic parameter belongs to the current candidate" would be perfectly reliable, so maybe this can be tackled in another PR. Alternatively, we can implement this binding behavior for generic parameters first, then have separate PRs for actually creating the new binding layers (i.e. this one and one for #24337). |
|
This pull request is stale because it has been open for 1 year with no activity. Contribute more commits on the pull request and rebase it on the latest devel, or it will be closed in 30 days. Thank you for your contributions. |
|
This pull request has been marked as stale and closed due to inactivity after 395 days. |
fixes #4858, fixes #10027, fixes #12552, fixes #15721, fixes #21331, fixes but does not test #18121 (maybe it should fail the match in this case?), refs #1214, follows up #24216, split from #24198
When an
ortype or a generic param constraint match a type with a convertible match, bind it to the branch that was deemed convertible rather than the matched type, so that a conversion can be generated. There were some required changes to make this work.ortypes now choose a "best matching" branch to use for the conversion. This branch is the earliest branch in the type list with the highest level type match. The "earliest" choice resolves the ambiguity in cases like matching an integer literal againstint16 | uint16. The compiler used to compile on these cases before (by just matching them asint), so to keep code working this ambiguity has to be resolved.When matching types to the constraint type of generic parameters, the compiler previously disabled all bindings to typeclasses (including
ortypes). This is so the bindings for the typeclasses in the constraint don't leak into the entire candidate, i.e. the binding forT: SomeIntegershould not be used for allSomeIntegers afterward. However this means we can't reuse the binding from anortypeclass when it's a convertible match, because we will lose both the information of it being a conversion match (since it becomes a generic match instead) and which branch of theortype matched (i.e. the type to convert to).To deal with this, we push a new type binding layer (see the refactor in #24216) for generic parameter constraints which contains all bindings to itself (except generic parameter bindings which are propagated up to the root). Then, if the constraint is an
ortype, we bind the generic param to the type that theortype was bound to in the type binding layer. We may not need to restrict toortypes here and just use the binding for any type that has a binding, but this is risky and I can't think of a reason any other typeclass would give something other than the matched type.There was also code that skipped
rangetypes for all bound generic types as mentioned in #10027, but this code broke the test for #10027, so it is removed, i.e.rangetypes can be bound to typeclasses now. Fixing the other issues may have removed the need for this skip, I don't know why it was there.ortypes also do not consider any type match belowisIntConv, for exampleisConvertible, to match, which is the cause of #4902, #15722 and #18697 (not sure aboutiterablethough). If this was just a limitation caused by the issues fixed in this PR (seems to be) then maybe we can loosen it to fix these issues, i.e. makeisConvertiblematch forortypes. But in another PR.