bind generic param/or
to constraint for conversion match
#24250
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
or
type 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.or
types 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
or
types). This is so the bindings for the typeclasses in the constraint don't leak into the entire candidate, i.e. the binding forT: SomeInteger
should not be used for allSomeInteger
s afterward. However this means we can't reuse the binding from anor
typeclass 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 theor
type 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
or
type, we bind the generic param to the type that theor
type was bound to in the type binding layer. We may not need to restrict toor
types 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
range
types for all bound generic types as mentioned in #10027, but this code broke the test for #10027, so it is removed, i.e.range
types 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.or
types also do not consider any type match belowisIntConv
, for exampleisConvertible
, to match, which is the cause of #4902, #15722 and #18697 (not sure aboutiterable
though). 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. makeisConvertible
match foror
types. But in another PR.