-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[ConstraintSystem] Return of the new disjunction favoring/selection algorithm #79461
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
base: main
Are you sure you want to change the base?
Conversation
@swift-ci please test source compatibility |
@swift-ci please test |
@swift-ci please build toolchain |
f785515
to
21a3705
Compare
@swift-ci please test |
@swift-ci please test source compatibility |
f442ec8
to
6a4b7e7
Compare
@swift-ci please test |
@swift-ci please test source compatibility |
@swift-ci please test |
@swift-ci please test source compatibility |
367b059
to
37e3e32
Compare
@swift-ci please test |
@swift-ci please test source compatibility |
Debug source compatibility failure is UPASS on Doggie which is expected. |
37e3e32
to
a7ac64a
Compare
d593771
to
d8608a3
Compare
@swift-ci please test |
d8608a3
to
d156df4
Compare
@swift-ci please clean test |
@swift-ci please test source compatibility |
@swift-ci please test Windows platform |
…wiftlang#79128)" This reverts commit 725bd91.
… matching Result type should only be matched if there are matches on arguments or there are no viable candidates.
For example, `??` operator could produce an optional type so `test(<<something>> ?? 0) could result in an optional argument that wraps a type variable. It should be possible to infer bindings from underlying type variable and restore optionality.
Disjunctions with a single element are sometimes introduced after disfavoring, so we need to make sure that they are always preferred during disjunction selection.
Since such choices are all but guaranteed to be worst than any other non-disfavored choice, let's attempt them last to avoid having to form a complete solution just to filter it out during ranking.
Optimizer now covers all of the most common ExpressibleBy*Literal protocols.
…ures If there are no-same type requirements and parameters use either concrete types or generic parameter types directly, the optimizer should be able to handle ranking. Currently candidate arguments are considered in isolation which makes it impossible to deal with same-type requirements and complex generic signatures.
… `nil` while ranking `==` and `!=` operators `==` and `!=` operators have special overloads that allow matching `nil` literal on either side even if wrapped type on the other side doesn't conform to `Equatable`.
…t` on `Dictionary` Just like a subscript on `Array` if key type matches the argument type exactly, the result of subscript operator should be a value type wrappend in an `Optional`.
…eneric paameter types For example passing `Int?` to `T` should be considered a match if `T` doesn't have any requirements that block it.
…nt behavior Thanks to `LinkedExprAnalyzer` unary argument hack was able to infer matching based on literals and arithmetic operator chains, let's preserve that behavior in a more principled manner.
…s based speculation New ranking + selection algorithm suffered from over-eagerly selecting operator disjunctions vs. unsupported non-operator ones even if the ranking was based purely on literal candidates. This change introduces a notion of a speculative candidate - one which has a type inferred from a literal or an initializer call that has failable overloads and/or implicit conversions (i.e. Double/CGFloat). `determineBestChoicesInContext` would reset the score of an operator disjunction which was computed based on speculative candidates alone but would preserve favoring information. This way selection algorithm would not be skewed towards operators and at the same time if there is no no choice by to select one we'd still have favoring information available which is important for operator chains that consist purely of literals.
…s are considered Some of the disjunctions are not supported by the optimizers but could still be a better choice than an operator. Using a non-score based preference mechanism first allows us to make sure that operator disjunctions are not selected too eagerly in some situations when i.e. a member (supported or not) could be a better choice. `isPreferable` currently targets only operators in result builder contexts but it could be expanded to more uses in the future.
…ameters and ternary expressions We need to have a notion of "complete" binding set before we can allow inference from generic parameters and ternary, otherwise we'd make a favoring decision that might not be correct i.e. `v ?? (<<cond>> ? nil : o)` where `o` is `Int`. `getBindingsFor` doesn't currently infer transitive bindings which means that for a ternary we'd only have a single binding - `Int` which could lead to favoring overload of `??` and has non-optional parameter on the right-hand side.
The test was slow with hacks but now it's much faster - takes about 63k scopes to solve, it could be improved by introducing new overloads of prefix `-` to stdlib.
…plyExpr`s The original hack never applied to subscripts.
…tors vs. non-operators The problem this is trying to solve is eager selection of operators over unsupported disjunctions, when matching operators let's take speculative information into account because it helps to make better choices in this case.
…arameter types When matching candidate like `[Int]` against `Array<Element>` we need to conservatively assume that if the nominals match the argument is a viable exact match because otherwise it's possible to skip some of the valid matches when other overload choice have generic parameters at the same parameter position.
…ments or variadic overloads This matches the behavior of the old hack where favoring choices were rolled back if `mustConsider` produced `true` which happened only for protocol requirements and variadic overload choice regardless of their viability.
Instead of checking both protocols, check one that matches best depending on where `String` literal candidate came from.
…ices are failable If all of the viable initializer overloads are failable, the only valid inference choice is an optional candidate type.
…hod which is printed at the end
…rator chains Most of them don't have any children but string interpolation does and that marks whole chain as unsupported.
These choices could be better than some other non-disfavored ones in certain situations i.e. when `async` overload is disfavored but appears in async context it's preferrable to a non-async overload choice. Note that the code that mimic old hacks still needs to filter on `@_disfavoredOverload` in few places to maintain source compatibility.
d156df4
to
a806a05
Compare
LinkedExprAnalyzer
playbook_OptionalNilComparisonType
as candidate fornil
while analyzing==
and!=
operatorsInt? -> T