Commit Graph

115 Commits

Author SHA1 Message Date
Clack Cole
a405fffebb [CSOptimizer] favor Any.Type for metatype args alongside Any fast-path
Resolves https://github.com/swiftlang/swift/issues/85020
2025-11-21 18:34:04 -07:00
Slava Pestov
23a7ca04bf Sema: Remove BindingSet::operator bool 2025-11-14 10:05:32 -05:00
Pavel Yaskevich
80e6cbf3ef Merge pull request #85460 from xedin/replace-checkconformancewithoutcontext-with-conformstoknownprotocol
[CSOptimizer] Use `conformsToKnownProtocol` to check whether paramete…
2025-11-13 07:40:36 -08:00
Pavel Yaskevich
62a917800d [CSOptimizer] Use conformsToKnownProtocol to check whether parameter conforms to ExpressibleBy{Array, Dictionary}Literal
The existing check is no-op because it would never produce a null for
`paramType` under the conditions in `else` branch. A better
API it use here is `conformsToKnownProtocol` just like in other cases.
2025-11-12 10:51:54 -08:00
Pavel Yaskevich
a01692ace1 [CSOptimizer] Skip ?? if it's involved in optional chain with unresolved result type
`??` operator is overloaded on optionality of its result. When the
first argument matches exactly, the ranking is going to be skewed
towards selecting an overload choice that returns a non-optional type.
This is not always correct i.e. when operator is involved in optional
chaining. To avoid producing an incorrect favoring, let's skip the this
disjunction when constraints associated with result type indicate
that it should be optional.

Simply adding it as a binding won't work because if the second argument
is non-optional the overload that returns `T?` would still have a lower
score.

Resolves: rdar://164201746
2025-11-11 15:21:33 -08:00
Pavel Yaskevich
c7b3b73708 Merge pull request #85391 from xedin/rdar-164247524
[CSOptimizer] Avoid favoring overloads that mismatch context on async
2025-11-10 09:52:17 -08:00
Hamish Knight
b26b0b783e [CS] Add null check for ParameterList in findFavoredChoicesBasedOnArity
rdar://164116965
2025-11-07 22:17:33 +00:00
Pavel Yaskevich
513caf2c9b [CSOptimizer] Avoid favoring overloads that mismatch context on async
This is a fix for the ported "calls with a single unlabeled argument"
hack. If overload doesn't match context on async effect, let's not favor
it because that is more important than defaulted parameters.

Resolves: rdar://164269641
2025-11-07 14:15:45 -08:00
Pavel Yaskevich
e1a6077117 [CSOptimizer] Update unary call favoring to include resolved member references
Update special favoring logic for unlabeled unary calls to support
non-overloads member references in argument positions.

The original hack missed a case where a type of a member is known
in advance (i.e. a property without overloads) because there as
another hack (shrink) for that.

This helps in situations like `Double(x)` where `x` is a property
of some type that is referenced using an implicit `self.` injected
by the compiler.

Resolves: rdar://161419917
2025-10-27 18:22:37 +09:00
Hamish Knight
3141b5a8cd [AST] NFC: Introduce PrintOptions::forDebugging 2025-09-21 23:19:06 +01:00
Pavel Yaskevich
df962a83c6 [CSOptimizer] Don't match nil to _OptionalNilComparisonType
This type is only intended for pattern matching against `nil`
and the solver shouldn't early attempt to infer this type for
`nil` for arguments of `==` and `!=` operators it should instead
be inferred from other argument or result.

Resolves: rdar://158063151
2025-09-01 20:47:56 -07:00
Pavel Yaskevich
0d33af78ca [CSOptimizer] Add support for opened existential arguments
Check whether it would be possible to match a parameter type
by opening an existential type of the candidate argument.

Resolves: rdar://158159462
2025-08-15 00:14:51 -07:00
Pavel Yaskevich
c46f9e4f45 [CSOptimizer] All the candidates should match Any parameter type
If the parameter is `Any` we assume that all candidates are
convertible to it, which makes it a perfect match. The solver
would then decide whether erasing to an existential is preferable.

Resolves: rdar://157644867
2025-08-13 14:59:54 -07:00
Pavel Yaskevich
9588d519c6 [CSOptimizer] Fix a conditional that ignores function type parameters to look through optionals
Since parameters that have function types don't participate in
ranking, function types that are wrapped in optionals should be
excluded as well, because it's possible to overload on that and
such overloads with optional types would gain an undue advantage.

For example:

```
func test(_: (() -> Void)?) {}
func test(_: () -> Void) {}

func compute(handler: () -> Void) {
  test(handler)
}
```

Without this change the second overload would be ignored and
the first one would be an exact match.

Resolves: rdar://157234317
2025-08-01 10:59:52 -07:00
Pavel Yaskevich
9445a9fca9 [CSOptimizer] Decrease an operator argument score only if requires optional injection
This makes sure that optional and non-optional types are ranked
uniformly when matched against a generic parameter type that
could accept either of them.

This is a more general fix for https://github.com/swiftlang/swift/pull/83365
2025-07-29 16:49:47 -07:00
Pavel Yaskevich
b264e27a75 [CSOptimizer] A narrow fix for nil coalescing operator optimization
`??` is overloaded on optionality of the second parameter,
prevent ranking the argument candidates for this parameter
if there are candidates that come from failable initializer
overloads because non-optional candidates are always going
to be better and that can skew the selection.

Resolves: rdar://156853018
2025-07-28 00:35:02 -07:00
Slava Pestov
30c7f4afa7 Sema: Handle ArchetypeType and DynamicSelfType in determineBestChoicesInContext()
This fixes a regression introduced in https://github.com/swiftlang/swift/pull/82574.

The test case demonstrates the issue: we would incorrectly choose the base class
overload of == if one of the parameters was an archetype or dynamic Self.

Fixes rdar://156454697.
2025-07-23 17:22:42 -04:00
Pavel Yaskevich
1f8e487e2e [CSOptimizer] Prefer logical infix operator if it has smaller overload set
Infix logical operators are usually not overloaded and don't
form disjunctions, but when they do, let's prefer them over
other operators when they have fewer choices because it helps
to split operator chains.
2025-07-08 00:10:47 -07:00
Pavel Yaskevich
979e0469e0 [CSOptimizer] Rework inferTypeOfArithmeticOperatorChain
- Expand the inference to include prefix and postfix unary operators
- Recognize previously resolved declaration and member references
  in argument positions and record their types.
- Expand reconciliation logic from Double<->Int to include other
  floating-point types and `CGFloat`.
2025-06-27 23:43:12 -07:00
Pavel Yaskevich
ef2be0d3f5 [CSOptimizer] Rank operators with the same score based on speculative status
If the scores are the same and both disjunctions are operators
they could be ranked purely based on whether the candidates
were speculative or not. The one with more context always wins.

Consider the following situation:

```swift
func test(_: Int) { ... }
func test(_: String) { ... }

test("a" + "b" + "c")
```

In this case we should always prefer ... + "c" over "a" + "b"
because it would fail and prune the other overload if parameter
type (aka contextual type) is `Int`.
2025-06-27 23:43:12 -07:00
Pavel Yaskevich
2520d40575 [CSOptimizer] Allow literal inference inside of operator chains
This is helpful in situations when all of the chained operators
have literal arguments because it would make sure that every
operator has the same score if there is no contextual type.
2025-06-27 23:43:12 -07:00
Pavel Yaskevich
479e61b020 [CSOptimizer] Adopt to removal of TypeBase::isArrayType() by switching to isArray() 2025-06-27 23:43:12 -07:00
Pavel Yaskevich
8037bbced2 [CSOptimizer] NFC: Adopt to changes in getParameterList() API 2025-06-27 23:43:12 -07:00
Pavel Yaskevich
eb78e27a08 [CSOptimizer] Consider choices marked as @_disfavoredOverload
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.
2025-06-27 23:43:12 -07:00
Pavel Yaskevich
ea47e3cc24 [CSOptimizer] NFC: Adopt new Constraint and ConstraintGraph APIs 2025-06-27 23:43:11 -07:00
Pavel Yaskevich
b90fc2b8c6 [CSOptimizer] Don't attempt to walk into literals while analyzing operator chains
Most of them don't have any children but string interpolation does
and that marks whole chain as unsupported.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
db0a9de996 [CSOptimizer] Account for the fact that sometimes all initializer choices are failable
If all of the viable initializer overloads are failable,
the only valid inference choice is an optional candidate type.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
e7b351d41d [CSOptimizer] NFC: Use builder pattern to construct DisjunctionInfo 2025-06-27 23:43:11 -07:00
Pavel Yaskevich
125abede66 [CSOptimizer] Detect when candidate comes from string interpolation
Instead of checking both protocols, check one that matches best
depending on where `String` literal candidate came from.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
5aa3859f17 [CSOptimizer] Disable unary argument hack if overload set has requirements 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
e280569988 [CSOptimizer] Fix scoring while matching against partially resolved parameter 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
1dab584f29 [CSOptimizer] Account for speculative scores only when matching operators 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
073b48c43b [CSOptimizer] Restrict unary argument legacy favoring behavior to ApplyExprs
The original hack never applied to subscripts.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
617338f250 [CSOptimizer] Prevent candidate inference from unresolved generic parameters 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
e2fe558956 [CSOptimizer] Introduce a way to preference disjunctions before scores 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
bcc749fa1a [CSOptimizer] Reset the overall score of operator disjunctions that is 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.
2025-06-27 23:43:11 -07:00
Pavel Yaskevich
df4ae0a546 [CSOptimizer] Update candidate selection to use arithmetic operator chain inference 2025-06-27 23:43:11 -07:00
Pavel Yaskevich
4eec3f6788 [CSOptimizer] Introduce a drop of inference to preserved unary argument 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.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
0525818a33 [CSOptimizer] Allow matching candidates with optional types against generic paameter types
For example passing `Int?` to `T` should be considered a match
if `T` doesn't have any requirements that block it.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
ac24a8e251 [CSOptimizer] Introduce _OptionalNilComparisonType as candidate for 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`.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
aedc4fe25e [CSOptimizer] Remove selectBestBindingDisjunction hack 2025-06-27 23:43:10 -07:00
Pavel Yaskevich
b936900eb8 [CSOptimizer] Support non-operator generic choices with simple signatures
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.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
2646efac98 [CSOptimizer] Expand literal support to bools, strings and dictionaries
Optimizer now covers all of the most common ExpressibleBy*Literal
protocols.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
0e0b5f9a80 [CSOptimizer] Always prefer a disjunction with a single active choice
Disjunctions with a single element are sometimes introduced after
disfavoring, so we need to make sure that they are always preferred
during disjunction selection.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
b96139eb5b [CSOptimizer] Emulate old hack for unary argument matching more precisely
Having it be part of the other matching wasn't a good idea because
previous "favoring" happened only in a few situations - if argument
was a declaration reference, application or (dynamic) subscript that
had overload choice selected during constraint generation.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
666aa24224 [CSOptimizer] Add support for ?? operator 2025-06-27 23:43:10 -07:00
Pavel Yaskevich
84d034c388 [CSOptimizer] Don't reduce the ranking for non-default literal types
Since each candidate and overload choice are considered independenty
there is no way to judge whether non-default literal type is going
to result in a worse solution than non-default one.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
0dfb2044ef [CSOptimizer] Infer types from init calls used as arguments
This used to be limited to Double/CGFloat and operator arguments
but it's safe to do in general.
2025-06-27 23:43:10 -07:00
Pavel Yaskevich
899b2bc1e9 [CSOptimizer] Allow matching against CGFloat as a contextual result type 2025-06-27 23:43:10 -07:00
Pavel Yaskevich
6c28cdfb78 [CSOptimizer] Infer argument candidates through optionals
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.
2025-06-27 23:43:10 -07:00