Commit Graph

139 Commits

Author SHA1 Message Date
Slava Pestov 7cd06a5088 Sema: Split off TypeVariableType.h/.cpp 2026-02-05 09:19:01 -05:00
Slava Pestov 2e60d29973 Sema: Add -solver-{disable,enable}-performance-hacks flags 2026-02-03 16:34:10 -05:00
Slava Pestov 5cbdf4938e Sema: Tiny improvement to debug output in selectDisjunction() 2026-01-28 18:21:01 +00:00
Slava Pestov fabe4b6315 Sema: Explicitly favor forced moves
If a disjunction has zero or one choices remaining, there's nothing
to lose by attempting it. This will become a more common occurrence
once disjunction pruning is enabled.
2026-01-26 21:48:59 +00:00
Slava Pestov 95a54ce82a Sema: Yet another constraint optimization pass
- Fixes https://github.com/swiftlang/swift/issues/55762
- Fixes rdar://32034560
2026-01-26 21:48:59 +00:00
Slava Pestov c30ff009d3 Sema: Better -debug-constraints output in selectDisjunction() 2026-01-26 21:33:16 +00:00
Slava Pestov d860523944 Merge pull request #86760 from slavapestov/solver-shuffle
Sema: Add -solver-shuffle-disjunctions= and -solver-shuffle-choices= flags for debugging
2026-01-24 12:30:43 -05:00
elsa 5e9f215f31 Merge pull request #86010 from elsakeirouz/rework-for-each-desugar
Rework ForEachStmt Desugaring
2026-01-24 13:55:51 +00:00
Slava Pestov 30f1b0187a Sema: Add -solver-shuffle-disjunctions= and -solver-shuffle-choices= flags for debugging 2026-01-23 20:02:21 -05:00
Hamish Knight d3270fdf1e [CS] Remove ValueWitness constraint
The specialized type-checking for `for` loops was the only client of
this, it's now unused.
2026-01-23 15:17:30 +00:00
Pavel Yaskevich 411d396eb8 Merge pull request #86695 from xedin/remove-old-perf-hacks
[ConstraintSystem] Remove old performance hacks from the solver and related flags
2026-01-22 09:01:50 -08:00
Pavel Yaskevich a33ec97216 [ConstraintSystem] Remove old performance hacks from the solver
The hacks have been disabled for a while now, so it's time to
completely remove them in favor of CSOptimizer.
2026-01-21 11:53:19 -08:00
Slava Pestov 7f7afd1629 Sema: Skip disabled constraints in computeDisjunctionInfo() 2026-01-21 13:20:40 -05:00
Slava Pestov f762829c1a Sema: Split off computeDisjunctionInfo() from determineBestChoicesInContext()
The diff looks horrible but it's just moving a block of code out
into its own function and decreasing the indent level. Should be NFC.
2026-01-21 13:20:39 -05:00
Slava Pestov 4e39c0e694 Sema: Fix over-eager early return from determineBestChoicesInContext() 2026-01-21 11:10:44 -05:00
Slava Pestov f74d94e4bf Sema: Extract scoreCandidateMatch() into a top-level function 2026-01-21 11:09:59 -05:00
Slava Pestov 2063c765b4 Sema: Add more logging to determineBestChoicesInContext() 2026-01-20 16:19:45 -05:00
Slava Pestov 611ceff5e0 Sema: Fix regression from floating point removal
In 7bcbe1b3f0, I forgot to scale the
value by 100 in one place. This wasn't caught by our test suite,
but it regressed the new test case I'm adding. We would select the
UnicodeScalar.init() overload taking an UInt8, and complain that
the scalar doesn't fit.
2026-01-17 23:20:29 -05:00
Slava Pestov 7bcbe1b3f0 Sema: Get rid of floating point arithmetic
I'm uncomfortable with the use of floating point arithmetic here.

Even though this is a performance heuristic, it actually impacts
solver behavior because of how choice favoring works, and because
disjunction selection order indirectly affects other broken solver
behaviors.

The constants used, like 0.01, 0.1, 0.7, etc. are not exactly
representable, so when they get added up the result might differ
from the "actual" result by a small amount.

Because of that, we don't want any "load bearing" behaviors where
someone's expression type checks quickly or in a certain way because
of pecularities of floating point arithmetic.

Instead, scale everything up by a factor of 100 and use integers.
2026-01-15 11:16:29 -05:00
Slava Pestov 302ff930e9 Sema: Remove areEqual() from determineBestChoicesInContext()
TypeBase::isEqual() canonicalizes both sides, so calling
getDesugaredType() first is not necessary.
2026-01-15 11:16:26 -05:00
Slava Pestov 3d1444353c Sema: Extract isSubclassOf() from determineBestChoicesInContext() 2026-01-15 11:16:26 -05:00
Slava Pestov 95769b59b9 Sema: Add debugging code to ConstraintSystem::selectDisjunction() 2026-01-08 09:44:42 -05:00
Slava Pestov 06f5eefcf5 Sema: Fix accidental mutation of DenseMap in ConstraintSystem::selectDisjunction()
The firstScore and secondScore bindings were references, so the
assignments to those were mutating the DenseMap unintentionally.

Refactor this code a bit, we don't want to just change the
bindings to rvalues because then we would copy the FavoredChoices
vector, so instead bind a const reference to the DisjunctionInfo
and dereference its fields instead.
2026-01-07 13:23:05 -05:00
Slava Pestov 74fa1e7f5e Sema: BindingSet::Literals can just be a vector and not a map 2025-12-13 21:16:43 -05:00
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