If argument matching fails in diagnostic mode, it can only mean
that it couldn't find any viable fixes to attempt, so let's try
injecting `.callAsFunction` when appropriate to help diagnose
possible mismatches related to ambiguous syntax.
In situations like `T(...) { ... }` where `T` is a callable type,
it's not immediately clear whether trailing closures are associated
with `.init` of `T` or implicit `.callAsFunction`. So if constructor
didn't match trailing closures, let's attempt to split them off and
form an implicit `.callAsFunction` call with them as a fallback.
Opened archetypes can be created in the constraint system, and the
existential type it wraps can contain type variables. This can happen
when the existential type is inferred through a typealias inside a
generic type, and a member reference whose base is the opened existential
gets bound before binding the generic arguments of the parent type.
However, simplifying opened archetypes to replace type variables is
not yet supported, which leads to type variables escaping the constraint
system. We can support cases where the underlying existential type doesn't
depend on the type variables by canonicalizing it when opening the
existential. Cases where the underlying type requires resolved generic
arguments are still unsupported for now.
Nested archetypes are represented by their base archetype kinds (primary,
opened, or opaque type) with an interface type that is a nested type,
as represented by a DependentMemberType. This provides a more uniform
representation of archetypes throughout the frontend.
Introduce a new primitive operation on opaque type archetypes that
canonicalizes a type within the environment of the opaque type
archetype without building the environment itself. Use it when matching
opaque archetype types in the solver.
Insert an implicit conversion from pack types to tuples with equivalent parallel structure. That means
1) The tuple must have the same arity
2) The tuple may not have any argument labels
3) The tuple may not have any variadic or inout components
4) The tuple must have the same element types as the pack
The heart of this patchset: An inference scheme for variadic generic functions and associated pack expansions.
A traditional variadic function looks like
func foo<T>(_ xs: T...) {}
Along with the corresponding function type
<T>(T [variadic]) -> Void
which the constraint system only has to resolve one two for. Hence it opens <T> as a type variable and uses each argument to the function to try to solve for <T>. This approach cannot work for variadic generics as each argument would try to bind to the same <T> and the constraint system would lose coherency in the one case we need it: when the arguments all have different types.
Instead, notice when we encounter expansion types:
func print<T...>(_ xs: T...)
print("Macs say Hello in", 42, "different languages")
We open this type as
print : ($t0...) -> ($t0...)
Now for the brand new stuff: We need to create and bind a pack to $t0, which will trigger the expansion we need for CSApply to see a coherent view of the world. This means we need to examine the argument list and construct the pack type <$t1, $t2, $t3, ...> - one type variable per argument - and bind it to $t0. There's also the catch that each argument that references the opened type $t0 needs to have the same parallel structure, including its arity. The algorithm is thus:
For input type F<... ($t0...), ..., ($tn..) ...> and an apply site F(a0, ..., an) we walk the type `F` and record an entry in a mapping for each opened variadic generic parameter. Now, for each argument ai in (a0, ..., an), we create a fresh type variable corresponding to the argument ai, and record an additional entry in the parameter pack type elements corresponding to that argument.
Concretely, suppose we have
func print2<T..., U...>(first: T..., second: U...) {}
print2(first: "", 42, (), second: [42])
We open print2 as
print2 : ($t0..., $t1...) -> Void
And construct a mapping
$t0 => <$t2, $t3, $t4> // eventually <String, Int, Void>
$t1 => <$t5> // eventually [Int]
We then yield the entries of this map back to the solver, which constructs bind constraints where each => exists in the diagram above. The pack type thus is immediately substituted into the corresponding pack expansion type which produces a fully-expanded pack type of the correct arity that the solver can actually use to make forward progress.
Applying the solution is as simple as pulling out the pack type and coercing arguments element-wise into a pack expression.
When evaluating whether code is within a closure that uses concurrency
features, use the type of the closure as it's known during type checking,
so that contextual information (e.g., it's passed to a `@Sendable` or
`async` parameter of function type) can affect the result. This
corrects the definition for doing strict checking within a minimal
context for the end result of the type-check, rather than it's initial
state, catching more issues.
Fixes SR-15131 / rdar://problem/82535088.
The new type, called ExistentialType, is not yet used in type resolution.
Later, existential types written with `any` will resolve to this type, and
bare protocol names will resolve to this type depending on context.
This ensures, among other things, that `@_predatesConcurrency` doesn't
affect the types of entities anywhere in a module compiled in Swift 6, so
we get stricter checking throughout.
When in "existing" Swift code that is Swift 5.x and has not adopted
concurrency, allow mismatches in function types that only involve
ABI-neutral concurrency changes (e.g., adding `@Sendable` or removing
a global actor) by downgrading the diagnostic to a warning. This
improves the story for incremental adoption of concurrency in an
existing code base.
As part of this, generalize the facility for downgrading an error to a
warning when performing diagnostics in the constraint solver, using the
new diagnostic behavior limits rather than duplicating diagnostics.
Despite being otherwise disconnected from the
constraint system, it's possible for it to affect
how we type-check tuple matches in certain cases.
This is due to the fact that:
- It can have a lower type variable ID than an
opened generic parameter type, so becomes the
representative when merged with it. And because it
has a different locator, this can influence
binding prioritization.
- Tuple subtyping is broken, as it's currently a
*weaker* relationship than conversion.
Therefore, temporarily restore this bit of logic
for language versions < 6. If possible, we should
try and fix tuple subtying in Swift 6 mode to not
accept label mismatches, so that it's not more
permissive than tuple conversion.
rdar://85263844
While checking validity of the optional chain, let's not assume
that the contextual type associated with is optional because
enclosing expression could too be invalid.
Resolves: rdar://85166519
Passing Double? to CGFloat? and vice versa is not supported but
there was one case which solver still allowed to get through -
optional chains, which is not fixed.