-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[ConstraintSystem] New "stable" disjunction selection algorithm #40748
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
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@swift-ci please test compiler performance |
@swift-ci please smoke test compiler performance |
Almost 9% reduction in leaf scopes in smoke test. |
Summary for main fullRegressions found (see below) Debug-batchdebug-batch briefRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (2)
debug-batch detailedRegressed (9)
Improved (11)
Unchanged (delta < 1.0% or delta < 100.0ms) (248)
Releaserelease briefRegressed (0)
Improved (2)
Unchanged (delta < 1.0% or delta < 100.0ms) (0)
release detailedRegressed (7)
Improved (158)
Unchanged (delta < 1.0% or delta < 100.0ms) (103)
|
8c8a2ba
to
b9aac87
Compare
@swift-ci please test source compatibility |
…o a separate method
… one that has none If one of the sides has no favored overloads, it's a strong enough indication that we know more about the other side.
Prelude. The core idea behind `shrink` is simple - reduce overload sets via a bottom-up walk'n'solve that would utilize previously discovered solutions along the way. This helps in some circumstances but requires rollbacks and AST modification (if choices produced by previous steps fail to produce solutions higher up). For some expressions, especially ones with multiple generic overload sets, `shrink` is actively harmful because it would never be able to produce useful results. The Algorithm. These changes integrate core idea of local information propagation from `shrink` into the disjunction selection algorithm itself. The algorithm itself is as follows - at the beginning use existing selection algorithm (based on favoring, active choices, etc.) to select the first disjunction to attempt, and push it to the stack of "selected" disjunctions; next time solver requests a disjunction, use the last selected one to pick the closest disjunction to it in the AST order preferring parents over children. For example: ``` + / \ * Float(<some variable e.g. `r` = 10)) / \ exp Float(1.0) | 2.0 ``` If solver starts by picking `Float(r)` first, it would then attempt `+`, `exp` in that order. If it did pick `Float(1.0)` then, the sequence is `*`, `+` and finally `exp`. Since the main idea here to is keep everything as local as possible along a given path, that means special handling for closures and tuples: - Closures: if last disjunction is a call with a trailing closure argument, and such argument is resolved (constraint are generate for the body) - use selection algorithm to peek next disjunction from the body of the closure, and solve everything inside before moving to the next member in the chain (if any). This helps with linked member expressions e.g. `.map { ... }.filter { ... }.reduce { ... }`; - Tuples: The idea here is to keep solving local to a current element until it runs out of disjunction, and then use selection algorithm to peek from the pool of disjunctions associated with other elements of the tuple. Resolves: SR-10130 Resolves: rdar://48992848 Resolves: rdar://23682605 Resolves: rdar://46713933
…rom common result compulation This is the situation where a property has the same name as a method e.g. ```swift protocol P { var test: String { get } } extension P { var test: String { get { return "" } } } struct S : P { func test() -> Int { 42 } } var s = S() s.test() // disjunction would have two choices here, one // for the property from `P` and one for the method of `S`. ``` In cases like this, let's exclude property overload from common result determination because it cannot be applied. Note that such overloads cannot be disabled, because they still have to be checked in diagnostic mode and there is (currently) no way to re-enable them for diagnostics.
b9aac87
to
6435083
Compare
Superseded by #63585 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Prelude.
The core idea behind
shrink
is simple - reduce overload sets viaa bottom-up walk'n'solve that would utilize previously discovered
solutions along the way. This helps in some circumstances but requires
rollbacks and AST modification (if choices produced by previous steps
fail to produce solutions higher up). For some expressions, especially
ones with multiple generic overload sets,
shrink
is actively harmfulbecause it would never be able to produce useful results.
The Algorithm.
These changes integrate core idea of local information propagation
from
shrink
into the disjunction selection algorithm itself.The algorithm itself is as follows - at the beginning use existing
selection algorithm (based on favoring, active choices, etc.) to
select the first disjunction to attempt, and push it to the stack
of "selected" disjunctions; next time solver requests a disjunction,
use the last selected one to pick the closest disjunction to it in
the AST order preferring parents over children.
For example:
If solver starts by picking
Float(r)
first, it would thenattempt
+
,exp
in that order. If it did pickFloat(1.0)
then, the sequence is
*
,+
and finallyexp
.Since the main idea here to is keep everything as local as possible
along a given path, that means special handling for closures and tuples:
Closures: if last disjunction is a call with a trailing closure argument,
and such argument is resolved (constraint are generate for the body) -
use selection algorithm to peek next disjunction from the body of the
closure, and solve everything inside before moving to the next member
in the chain (if any). This helps with linked member expressions e.g.
.map { ... }.filter { ... }.reduce { ... }
;Tuples: The idea here is to keep solving local to a current element
until it runs out of disjunction, and then use selection algorithm to
peek from the pool of disjunctions associated with other elements of
the tuple.
Resolves: SR-10130
Resolves: rdar://48992848
Resolves: rdar://23682605
Resolves: rdar://46713933