Commit Graph

28352 Commits

Author SHA1 Message Date
Pavel Yaskevich
19350d9737 Merge pull request #63585 from xedin/solver-perf
[CSSolver] Implementation of disjunction choice favoring algorithm
2024-12-18 09:47:59 -08:00
Gábor Horváth
4ee8e0df26 Merge pull request #78115 from swiftlang/gaborh/cpp-span-unsafe
[cxx-interop] Make sure C++ span is imported as @unsafe
2024-12-18 13:20:41 +00:00
Anthony Latsis
b6def6ec71 Merge pull request #77892 from AnthonyLatsis/magnolia-grandiflora
Sema: Subscript called with opened existential cannot produce lvalue if result is type-erased
2024-12-18 12:25:45 +00:00
Pavel Yaskevich
bc3a15fbe6 [CSOptimizer] Disable CGFloat -> Double conversion for unary operators
Some of the unary operators, i.e. prefix `-`, don't have
CGFloat variants and expect generic `FloatingPoint` overload
to match CGFloat type. Let's not attempt `CGFloat` -> `Double`
conversion for unary operators because it always leads
to a worse solutions vs. generic overloads.
2024-12-18 00:22:49 -08:00
Pavel Yaskevich
636525ebd9 Merge pull request #78171 from xedin/rdar-140300022
[TypeChecker/SILGen] Allow `any Sendable` to match `Any` while matching generic arguments
2024-12-17 20:24:34 -08:00
Pavel Yaskevich
860ae08d1b [CSOptimizer] Mark bitwise operators as supported 2024-12-17 16:44:18 -08:00
Pavel Yaskevich
43ca7dfff9 [CSOptimizer] Simplify handling of non-applied disjunctions
If a disjunction doesn't have an application, let's prefer
it if it's passed as an argument to an operator application
or involved in a member chain, in such situations attempting
a disjunction could provide context to parent call/member chain.

If disjunction is passed as an unapplied reference to some
parameter i.e. `<base>.map(String.init(describing:))` we don't
favor it for now because optimizer cannot do enough checking
to determine whether preferring such disjunction would help
make forward progress in solving by pruning some space or
providing additional context.
2024-12-17 16:44:06 -08:00
Anthony Latsis
6612c9cf89 Sema: Subscript called with opened existential cannot produce lvalue if result is type-erased 2024-12-17 23:03:38 +00:00
Pavel Yaskevich
f7d81d5271 [TypeCheckEffects] Downgrade missing await to a warning for initializer calls with a single unlabeled parameter
Mitigation for a historic incorrect type-checker behavior
caused by one of the performance hacks that used to favor
sync constructor overload over async one in async context
if initializers take a single unlabeled argument.

```swift
struct S {
  init(_: Int) {}
  init(_: Int) async {}
}

func test(v: Int) async { S(v) }
```

The type-checker should use `init(_: Int) async` in `test` context
but used to select the sync overload. The hack is now gone but we
need to downgrade an error to a warning to give the developers time
to fix their code.
2024-12-17 11:36:42 -08:00
Pavel Yaskevich
c767f7aff7 [ConstraintSystem] Fix getEffectiveOverloadType handling of mutating methods 2024-12-17 11:36:42 -08:00
Pavel Yaskevich
95b47aead6 [CSOptimizer] Reduce overload types before ranking
This would make sure that any same-type requirements to a concrete
type are substituted with such types which is especially important
for SIMD operators like `&{+, -}` because they have `Scalar == (U)Int*`
requirements.
2024-12-17 11:36:42 -08:00
Pavel Yaskevich
40a41c82d9 [CSBindings] Don't attempt to strip optional for closure result types
Let's not perform $T? -> $T for closure result types to avoid having
to re-discover solutions that differ only in location of optional
injection.

The pattern with such type variables is:

```
$T_body <conv/subtype> $T_result <conv/subtype> $T_contextual_result
```

When `$T_contextual_result` is `Optional<$U>`, the optional injection
can either happen from `$T_body` or from `$T_result` (if `return`
expression is non-optional), if we allow  both the solver would
find two solutions that differ only in location of optional
injection.
2024-12-17 11:36:42 -08:00
Pavel Yaskevich
56d6635e46 [CSOptimizer] Implement special prioritization rules for result builder contexts
Prioritize `build{Block, Expression, ...}` and any chained
members that are connected to individual builder elements
i.e. `ForEach(...) { ... }.padding(...)`, once `ForEach`
is resolved, `padding` should be prioritized because its
requirements can help prune the solution space before the
body is checked.
2024-12-17 11:36:42 -08:00
Pavel Yaskevich
bf8ae3bc1b [CSOptimizer] Allow only widening CGFloat->Double conversions while matching candidate arguments
Allow CGFloat -> Double widening conversions between
candidate argument types and parameter types. This would
make sure that Double is always preferred over CGFloat
when using literals and ranking supported disjunction
choices. Narrowing conversion (Double -> CGFloat) should
be delayed as much as possible.
2024-12-17 11:36:42 -08:00
Pavel Yaskevich
cb876cbd9e [CSSimplify] CGFloat-Double: Rank narrowing correctly when result is injected into an optional
If result of `CGFloat` -> `Double` conversion is injected into an optional
it should be ranked based on depth just like when locator is fully simplified.

For example:

```swift
func test(v: CGFloat?) {
   _ = v ?? 2.0 / 3.0
}
```

In this expression division should be performed on `Double` and result
narrowed down (based on the rule that narrowing conversion should always
be delayed) but `Double` -> `CGFloat?` was given an incorrect score and
instead of picking `?? (_: T?, _: T) -> T` overload, the solver would
use `?? (_: T?, _: T?) -> T?`.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
b7e7493076 [CSBindings] Prevent BindingSet::isViable from dropping viable bindings (v2)
The original attempt to do this was reverted by https://github.com/swiftlang/swift/pull/77653

The problem is that the fix was too broad, I narrowed it down to
non-exact uses of stdlib collections that support upcasts.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
87cd5f8733 [CSOptimizer] Add support for chained members without arguments
If disjunction represents a member reference that has no arguments
applied, let's score that as `1` to indicate that it should be priorized.

This helps in situations like `a.b + 1` where resolving `a.b` member
chain helps to establish context for `+`.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
867e64182f [CSOptimizer] Mark compiler synthesized disjunctions as optimized
If a disjunction has favored choices, let's mark it as optimized
with a high score to make sure that such disjunctions are prioritized
since only disjunctions that could have their choices fovored
independently from the optimization algorithm are compiler synthesized
ones for things like IUO references, explicit coercions etc.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
15c773b9d7 [CSOptimizer] Make a light-weight generic overload check if some requirements are unsatisfiable
If some of the requirements of a generic overload reference other
generic parameters, the optimizer won't be able to satisfy them
because it only has candidates for one (current) parameter. In
cases like that, let's fallback to a light-weight protocol conformance
check instead of skipping an overload choice altogether.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
c2a55886f0 [CSOptimizer] Fix selectDisjunction to use favored choices even if disjunction was not optimized
Some disjunctions e.g. explicit coercions, compositions of restrictions,
and implicit CGFloat initializers have favored choices set independently
from optimization algorithm, `selectDisjunction` should account for
such situations.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
9fb73143f6 [CSOptimizer] Limit "old" behavior compatibility to unlabeled unary arguments
`favorMatchingOverloadExprs` used `getUnlabeledUnaryExpr` and we
need to mimic that exactly because there is code that relies on
this behavior now.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
8bd288447f [CSGen] NFC: Remove obsolete ConstraintSystem::{get, set}FavoredType 2024-12-17 11:36:41 -08:00
Pavel Yaskevich
2fdd4b6c35 [CSOptimizer] Allow literal arguments to match parameters that conform to ExpressibleBy{Integer, Float}Literal
`scoreCandidateMatch` needs to reflect the fact that literal can
assume any type that conforms to `ExpressibleBy{Integer, Float}Literal`
protocol but since such bindings are non-default and alway produce
a worse solution vs. default literal types if all of the arguments
are literals let's use only exact matches otherwise there is a chance
of "over-favoring" and creating more work for ranking.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
9b62c84a4f [CSOptimizer] Adjust scoreCandidateMatch to indicate when match cannot be decided
It is not always possible to match candidate types against corresponding
parameter types for certain overloads i.e. when parameter is an associated type.

`scoreCandidateMatch` needs to be able to indicate that to the caller
to allow it to move to the next parameter (if any) without failing the
overload choice when the match cannot be established.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
6caf1ccbb2 [CSOptimizer] Fix Double<->CGFloat implicit conversion support when arguments are literals
Passing Double to CGFloat as well as vice versa constitutes an exact match.
2024-12-17 11:36:41 -08:00
Pavel Yaskevich
e30587bda4 [CSOptimizer] A more comprehensive generic overload checking when candidates are fully resolved
Use `checkGenericRequirements` to check whether all of the requirements
placed on a particular parameter match, that gives us a lot of confidence
that the overload should be favored.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
a3a3ec4fe0 [CSOptimizer] Restore old hack behavior which used to favor overloads based on arity matches
This maintains an "old hack" behavior where overloads  of some
`OverloadedDeclRef` calls were favored purely based on number of
argument and (non-defaulted) parameters matching.

This is important to maintain source compatibility.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
802f5cd105 [CSOptimizer] Desugar types before checking for equality 2024-12-17 11:36:40 -08:00
Pavel Yaskevich
8d5cb112ef [ConstraintSystem] Narrowly disable tryOptimizeGenericDisjunction when some of the arguments are number literals
Don't attempt this optimization if call has number literals.
This is intended to narrowly fix situations like:

```swift
func test<T: FloatingPoint>(_: T) { ... }
func test<T: Numeric>(_: T) { ... }

test(42)
```

The call should use `<T: Numeric>` overload even though the
`<T: FloatingPoint>` is a more specialized version because
selecting `<T: Numeric>` doesn't introduce non-default literal
types.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
f2a6677a6d [CSOptimizer] Infer argument candidates from calls to Double and CGFloat constructors
Helps situations like `1 + {Double, CGFloat}(...)` by inferring
a type for the second operand of `+` based on a type being constructed.

Currently limited to Double and CGFloat only since we need to
support implicit `Double<->CGFloat` conversion.

Helps situations like `1 + CGFloat(...)` by inferring a type for
the second operand of `+` based on a type being constructed.
Currently limited to known integer, floating-point and CGFloat types
since we know how they are structured.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
59109c2d60 [CSOptimizer] Score all of the overload choices matching on literals uniformly
Regardless of whether an overload choice matched on one or more
literal candidate types assign it a fixed score to make sure that
we always prefer outmost disjunction in cases like `test(1 + 2 + 3)`
since it gives us a better chance to prune once there is a contextual
type.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
6fb6d1cf90 [CSOptimizer] Enable ranking of Int*, Float{80} and Double initializers 2024-12-17 11:36:40 -08:00
Pavel Yaskevich
8818d399f9 [CSOptimizer] Rank disjunctions based on score only if both sides are supported 2024-12-17 11:36:40 -08:00
Pavel Yaskevich
3996b25fbd [CSOptimizer] Rank results of operators regardless of whether anything is known about parameters
When operators are chained it's possible that we don't know anything
about parameter(s) but result is known from the context, we should
use that information.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
23589add74 [CSOptimizer] Average score should reflect number of defaulted parameters 2024-12-17 11:36:40 -08:00
Pavel Yaskevich
8a918e2369 [CSOptimizer] Don't optimize (implicit) calls with code completion arguments
`containsIDEInspectionTarget` doesn't work for implicit argument
lists, but luckily implicit code completion expressions cannot
be injected into arguments, so we can check whether whether they
appear at an argument position and prevent optimization.
2024-12-17 11:36:40 -08:00
Pavel Yaskevich
deca9b61c5 [CSOptimizer] attempt to rank only standard/simd operators and fully concrete overload sets 2024-12-17 11:36:39 -08:00
Pavel Yaskevich
3819ddfb40 [CSOptimizer] Record best scores for each disjunction and use them in selectDisjunction
If there is no single best disjunction use best scores first
to determine minimum with fallback to favored and/or active
choice counts.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
cf05405eae [CSOptimizer] Let determineBestChoicesInContext return the best disjunction if one is available
If there is one overall best disjunction, let's attempt it first.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
527de22bec [CSOptimizer] Emulate old behavior related to favoring of unary calls to members
Preserves old behavior where for unary calls to members
the solver would not consider choices that didn't match on
the number of parameters (regardless of defaults) and only
exact matches were favored.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
d69b6a0594 [CSOptimizer] Prefer homogeneous arithmetic operator overloads when argument(s) or result match
This is an opportunistic optimization based on the operator
use patterns where homogeneous operators are the most
heavily used ones.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
1760bd1f1e [CSOptimizer] Remove an outdated optimization to compare resolved argument types with all else equal
This is already accounted for by `determineBestChoicesInContext`
and reflected in the overall score, which means that we no longer
need to use this in vacuum.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
c429f5b9ec [CSOptimizer] NFC: Switch from llvm::Optional to std::optional post-rebase 2024-12-17 11:36:39 -08:00
Pavel Yaskevich
2869dff995 [CSOptimizer] Increase score when type matches opaque type
Since erasure of a concrete type into an existential value yields
score of 1, we need to bump the score in cases where a type
passed to a generic parameter satisfies all of its protocol
conformance requirements and that parameter represents an
opaque type.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
0fc6806922 [CSOptimizer] NFC: Switch to llvm::Optional 2024-12-17 11:36:39 -08:00
Pavel Yaskevich
da65333d41 [CSOptimizer] NFC: Adjust conformance check to use ConstraintSystem::lookupConformance 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
957a5f4270 [CSOptimizer] Treat all type parameters equally
Dependent members just like generic parameter types could
have associated protocol conformances which give us a glimpse
into whether arguments could possibly match.
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
2c44e37948 [CSStep] Remove disjunction pruning logic from DisjunctionStep
Since old favoring mechanism has been removed this is dead code
now because nothing is going to equate disjunction constraints.
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
11b897b32f [CSOptimizer] Relax candidate type requirements from equality to set of no-impact conversions
Candidate is viable (with some score) if:

- Candidate is exactly equal to a parameter type
- Candidate type differs from a parameter type only in optionality
- Parameter is a generic parameter type and all conformances are matched by a candidate type
- Candidate tuples matches a parameter tuple on arity
- Candidate is an `Array<T>` and parameter is an `Unsafe*Pointer`
- Candidate is a subclass of a parameter class type
- Candidate is a concrete type and parameter is its existential value (except Any)
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
cb1cb2018d [CSOptimizer] Use matchCallArguments to establish argument-to-parameter relationships
This helps to find defaulted parameter positions as well.
2024-12-17 11:36:38 -08:00