All callers can trivially be refactored to use ModuleDecl::lookupConformance()
instead. Since this was the last flag in ConformanceCheckOptions, we can remove
that, too.
Introduce `SK_Hole` which is used to count a number of "holes" in
a given solution. It is used to distinguish solutions with fewer holes.
Also it makes it possible to check whether a solution has holes but
no fixes, which is an issue and such solution shouldn't be applied
to AST.
This is a follow-up to https://github.com/apple/swift/pull/30113
which cased a regression because it was placed under a check which
allows direct supertypes to be inferred if previous (failing) binding
has a supertype as well which has nothing to do with collection
inference.
Let's combine supertype check and inference logic to avoid such
confusion in the future.
Resolves: rdar://problem/60501780
Reverts apple/swift#30006. It caused a regression that we'd like to address before re-landing:
```swift
struct X {
var cgf: CGFloat
}
func test(x: X?) {
let _ = (x?.cgf ?? 0) <= 0.5
}
```
This reverts commit 0a6b444b49.
This reverts commit ed255596a6.
This reverts commit 3e01160a2f.
This reverts commit 96297b7e39.
Resolves: rdar://problem/60185506
Instead of always opening argument type represented by a collection
without type variables (to support subtyping when element is a labeled tuple),
let's try original type first and if that fails use a slower path with
indirection which attempts `array upcast`. Doing it this way helps to
propagate contextual information faster which fixes a performance regression.
Resolves: rdar://problem/54580247
Let's delay attempting any bindings for type variables representing
parameters or result type of the closure until the body is "opened"
because it's impossible to infer a full set of bindings until all
constraints related to a closure have been generated.
Resolves: rdar://problem/59741308
Enable solver to transitively infer bindings through argument conversion
constraints. That helps to infer bindings for (generic) parameters
from their arguments e.g.
```swift
func foo<T: ExpressibleByStringLiteral>(_: String, _: T) -> T {
fatalError()
}
func bar(_: Any?) {}
func test() {
bar(foo("", ""))
}
```
In this case `T` can currently only be inferred as `Any?`
(based on parameter type of `bar`) although a complete
set of bindings for that type variable includes `String`
as well, which comes from use of `T` in argument position.
Resolves: rdar://problem/56212087
Fix a case where favoring didn't account for "bound" type variable
being wrapped into optional(s) (disjunctions like that are used for
optional conversions). Doing so makes sure that closure result type
is not bound before the body of the closure is "opened", that's
important because body could provide additional context required
to bind result type e.g. `{ $0 as? <Type> }`.
Resolve: rdar://problem/59208419
* If there is a disjunction associated with closure type e.g.
coercion to some other type `_ = { $0 } as (Int32) -> Void`
* If there is a disjunction associated with a collection which
could provide more context to the constraint solver.
If there is `subtype` relationship between two type variables
binding inference algorithm attempts to infer supertype bindings
transitively, but it doesn't check whether some of the new types
are already included in the set, which leads to duplicate solutions.
If there is a subtype relationship between N types we have to make
sure that type chain is attempted in reverse order because we can't
infer bindings transitively through type variables and attempting
it in any other way would miss potential bindings across the chain.
Even if contextual closure type has type variables inside
prefer it over disjunction because it provides a lot of
contextual information early which helps to solve the system
faster.
This constraint connects type variable representing a closure
expression to its inferred type and behaves just like regular
`Defaultable` constraint expect for type inference where it's
used only if there are no contextual bindings available.
When type checking the body of a function declaration that has a function
builder on it (e.g., `@ViewBuilder var body: some View { ... }`), create a
constraint system that is responsible for constraint generation and
application, sending function declarations through the same code paths
used by closures.
Introduce a new kind of constraint, the "value witness" constraint,
which captures a reference to a witness for a specific protocol
conformance. It otherwise acts like a more restricted form of a "value
member" constraint, where the specific member is known (as a
ValueDecl*) in advance.
The constraint is effectively dependent on the protocol
conformance itself; if that conformance fails, mark the type variables
in the resolved member type as "holes", so that the conformance
failure does not cascade.
Note that the resolved overload for this constraint always refers to
the requirement, rather than the witness, so we will end up recording
witness-method references in the AST rather than concrete references,
and leave it up to the optimizers to perform devirtualization. This is
demonstrated by the SIL changes needed in tests, and is part of the
wider resilience issue with conformances described by
rdar://problem/22708391.
There was a single place where it was used to determine whether
a binding comes from an argument conversion constraint. Since
constraint locator is part of the binding now it's possible to
use it instead and remove unused accessor.
Since `binding` has all of the required information now it's possible
to use its `locator` as a source of type variable assignment
(`Bind` constraint) in `TypeVariableBinding::attempt` which helps
to improve diagnostics.
Unify all of the fields of `PotentialBinding` which have to do with
location information into a single field with is either a constraint
(for regular bindings) or constraint locator (for "holes").
This helps to reduce the amount of space used by `PotentialBinding`
as well as propagate more contextual information when binding gets
attempted.
It might be either impossible to infer the base because there is
no contextual information e.g. `_ = .foo` or there is something
else wrong in the expression which disconnects member reference
from its context.
diagnosing failures in applySolutionFixes, coalesce fixes and
diagnose failures in one method on ConstraintFix.
This eliminates the need for the `DefaultGenericArgument` fix (which
was renamed from `ExplicitlySpecifyGenericArguments`) to have an
array of missing parameters, which was only used when the fixes were
coalesced. Instead, the coalesced arguments are used to create the
`MissingGenericArgumentsFailure` diagnostic directly.
automatically.
This commit also renames `ConstraintSystem::recordHole/isHole` to
`recordPotentialHole` and `isPotentialHole` to make it clear that
we don't know for sure whether a type variable is a hole until it's
bound to unresolved.
in the constraint system over a different binding or disjunction.
In other words, we will only choose to bind a hole to `Any` if there
are no other bindings and no disjunctions.
all cases of missing generic parameters.
In `ComponentStep::take` when there are no bindings or disjunctions, use hole
propagation to default remaining free type variables that aren't for generic
parameters and continue solving. Rather than using a defaultable constraint for
holes, assign a fixed type directly when we have no bindings to try.
A "hole" is a type variable which type couldn't be determined
due to an inference failure e.g. missing member, ambiguous generic
parameter which hasn't been explicitly specified.
It is used to propagate information about failures and avoid
recording fixes which are a consequence of earlier failures e.g.
```swift
func foo<T: BinaryInteger>(_: T) {}
struct S {}
foo(S.bar) // Actual failure here is that `S` doesn't have a member
// `bar` but a consequence of that failure is that generic
// parameter `T` doesn't conform to `BinaryInteger`.
```
One-way constraint expressions, which are the only things that
introduce one-way constraints at this point, want to look through
lvalue types to produce values. Rename OneWayBind to OneWayEqual, map
it down to an Equal constraint when it is simplified (to drop
lvalue-ness), and apply that coercion during constraint application.
Part of rdar://problem/50150793.
Introduce the notion of "one-way" binding constraints of the form
$T0 one-way bind to $T1
which treats the type variables $T0 and $T1 as independent up until
the point where $T1 simplifies down to a concrete type, at which point
$T0 will be bound to that concrete type. $T0 won't be bound in any
other way, so type information ends up being propagated right-to-left,
only. This allows a constraint system to be broken up in more
components that are solved independently. Specifically, the connected
components algorithm now proceeds as follows:
1. Compute connected components, excluding one-way constraints from
consideration.
2. Compute a directed graph amongst the components using only the
one-way constraints, where an edge A -> B indicates that the type
variables in component A need to be solved before those in component
B.
3. Using the directed graph, compute the set of components that need
to be solved before a given component.
To utilize this, implement a new kind of solver step that handles the
propagation of partial solutions across one-way constraints. This
introduces a new kind of "split" within a connected component, where
we collect each combination of partial solutions for the input
components and (separately) try to solve the constraints in this
component. Any correct solution from any of these attempts will then
be recorded as a (partial) solution for this component.
For example, consider:
let _: Int8 = b ? Builtin.one_way(int8Or16(17)) :
Builtin.one_way(int8Or16(42\
))
where int8Or16 is overloaded with types `(Int8) -> Int8` and
`(Int16) -> Int16`. There are two one-way components (`int8Or16(17)`)
and (`int8Or16(42)`), each of which can produce a value of type `Int8`
or `Int16`. Those two components will be solved independently, and the
partial solutions for each will be fed into the component that
evaluates the ternary operator. There are four ways to attempt that
evaluation:
```
[Int8, Int8]
[Int8, Int16]
[Int16, Int8]
[Int16, Int16]
To test this, introduce a new expression builtin `Builtin.one_way(x)` that
introduces a one-way expression constraint binding the result of the
expression 'x'. The builtin is meant to be used for testing purposes,
and the one-way constraint expression itself can be synthesized by the
type checker to introduce one-way constraints later on.
Of these two, there are only two (partial) solutions that can work at
all, because the types in the ternary operator need a common
supertype:
[Int8, Int8]
[Int16, Int16]
Therefore, these are the partial solutions that will be considered the
results of the component containing the ternary expression. Note that
only one of them meets the final constraint (convertibility to
`Int8`), so the expression is well-formed.
Part of rdar://problem/50150793.
Simplify the interface to gatherConstraints() by performing the
uniquing within the function itself and returning only the resulting
(uniqued) vector of constraints.