While shrinking we have to allocate containers for the reduced domains
for some of the candidates, it's currently done using permanent arena
of the `ASTContext` allocator. This patch changes candidate solver to
use arena associated with the parent constraint system, which significantly
limits lifetime of domain containers.
This was initially added to avoid "expression was too complex" in a
case where we were not previously reporting it for -swift-version 3
but should have been. In retrospect this seems misguided since
although we would not like to regress on "too complex" expressions, we
really don't want to silently continue in the cases where we decide an
expression is "too complex", but where we have a solution that we
could use. It's better to fail.
When trying to identify candidates for shrinking we are missing the case
when apply expression is a source of the assignment operator, which leads
to incorrect results in some situations, because shrink is going to miss
some required contextual information about assignment.
Resolves: rdar://problem/33190087
Split out the code for selecting potential bindings into a separate file
as a first step before refactoring it for improved clarity and ease of
modification.
In some situations e.g. while trying to shrink domains of the type
variables before attempting search, use a flag to tell constraint
system to retain all of the viable solutions otherwise solver could
loose some of the information required to produce complete solution.
Resolves: rdar://problem/32726044
By default, end expression type checking after the elapsed process time
is more than 60 seconds for the current expression. This threshold can
be overridden by using -solver-expression-time-threshold=<seconds>.
Resolves rdar://problem/32859654
Calls involving single trailing closure arguments require special
handling because we don't have as much contextual information
about function/argument types as in with regular calls, which means
that diagnosing such situations only by `visitApplyExpr`
yields subpar results.
Resolves: SR-4836.
Track outcomes of `conformsToProtocol` calls in `simplifyConformanceConstraints`
to be able to validate conformances when solution is formed to avoid returning
solutions with nominal types with invalid conformances to protocols.
There is a short-circuiting hack in the constraint solver that speeds up
solving, but isn't generally sound. If we allow unavailable decls to be
considered "favored", this can fire and result in our choosing a
solution that involves the unavailable decl where other solutions exist.
Fixes rdar://problem/32570734.
Restrict skipping of the generic overloads only to the situations
when non-generic solution doesn't have any restrictions/fixes, because
there is a possibility that generic overload could produce a better
solution.
Resolves: rdar://problem/32204609.
`FreeTypeVariableBinding::GenericParameters` mode allowed to bind
all free type variables with fresh generic parameter types, which
is incorrect (at least) if there are multiple generic solutions
present, because such parameters couldn't be compared.
This mode was used for code completion, which is now switched to use
`FreeTypeVariableBinding::UnresolvedType` instead.
Add additional checking for complexity of the shrinking candidate
given the number of the expressions solved so far and total number
of disjunctions present. This allows us to bail quicker in complex
expression cases which, at the very least, produces an error instead
of being "stuck" in solver for a long time.
Resolves: rdar://problem/32034560
Consolidate some of the attributes and operations common to disjunction choice
in new `DisjunctionChoice` class, which simplifies implementation of the
`ConstraintSystem::solveSimplified` method related to overload selection.
The old TVO_MustBeMaterializable is now equivalent to
!TVO_CanBindToLValue && !TVO_CanBindToInOut.
I tried to update all usages of createTypeVariable() to
pass TVO_CanBindToInOut unless they explicitly passed
TVO_MustBeMaterializable before.
However, in reality TVO_CanBindToInOut is the rare case;
we can remove this flag gradually over time to fix
crashes and diagnostics.
The openType() function did two things:
- Replace unbound generic types like 'G' with fresh type variables
applied to bound generic types, like 'G<$T0>'.
- Replace generic parameters with type variables from the replacement
map.
The two behaviors were mutually exclusive and never used from the
same call site, so split them up into two independent functions.
Also, eliminate ConstraintSystem::openBindingType() since it was only
used in one place and could be expressed in terms of existing functions.
Add logging before solving each of the candidates considered for
shrinking with information about sub-expression and new constraint system.
At the end of the candidate solving print each of the produced solutions.
This reverts commit
ecfa406fc5, which was reinstating
3c5b393e0c.
It does not revert one test change from that commit, because
inexplicably one of the tests is still failing, probably due to some
other changes that have happened since. I'm leaving a ticket open to
investigate.
I've added one of the new cases that is failing as a result of this
change.
This is being reverted not because of bugs in this particular commit,
but because it seems to be exposing other bugs in the type checker that
are resulting in source compatibility problems. We need to shake these
other bugs out of the type checker before bringing this change back.
The "skip generic operators" heuristic within the constraint solver is
fairly awful, because it is known to miss reasonable solutions. Make
is slightly more narrow by only skipping generic operators when the
concrete operator we found was symmetric.
It is useful to set a breakpoint on ErrorType::get(ASTContext)
to see what is going wrong immediately instead of after the
fact when an ErrorType pops up where you don't expect it.
Unfortunately associated type inference, domain shrinking and
the type cleanup RAII utility would all build ErrorTypes even
with valid code.
Refactor things a bit so that this is no longer the case; at
least now the standard library and overlays build with
'assert(false)' inserted into ErrorType::get(ASTContext).
ErrorType::get(Type) is still expected to come up in associated
type inference since it is used as a signal while sorting
through potential type witness candidates.
Recent changes to the stdlib resulted in some expressions involving
literals and operators that have both generic and non-generic overloads
to become ambiguous. The ambiguity is due to an old performance hack in
the solver which unfortunately needs to remain in place at the moment to
avoid regressing expression type checker performance.
This commit changes the performance hack a bit in that instead of
stopping visiting the options in a disjunction as soon as we have a
solution involving non-generic operators and come across a constraint
involving generic operators, we instead continue visiting the elements
in the disjunction, but just skip over the generic operators.
Fixes rdar://problem/31695865 and rdar://problem/31698831.
We previously used a simple heuristic of visiting the disjunction with
the fewest number of elements in it.
Instead, this commit introduces a new way to select the best disjunction
to explore based on attempting disjunctions based on either how much
information we have about the associated type variables (e.g. how many
of the arguments of a function call in the case of bind overload
disjunctions) or by other criteria that help constraint the search or
split the connected components (e.g. coercions and calls to
initializers).
A key part of the improvement here is allowing the type checker to
attempt bindings of types to type variables when there are still
argument conversion constraints between type variables in the
system. The insight here is if there are no other constraints blocking
an attempt to bind types and we have types to try, we will be able to
test those types against active conformance constraints and potentially
fail much earlier while solving.
Visiting disjunctions in a different order exposed some other problems
with the type checker including a couple cases where map is used that
are now considered ambiguous due to problems in how we are ranking
solutions.
I measured an 11-13% reduction in type checking time for the standard
library using a release build of the compiler.
When determining whether our inference of an optional type should add
a layer of optionality, look through lvalue types.
Fixes rdar://problem/31779785.
We have various hacks in the constraint solver to improve the
compile-time performance characteristics of operators. Some of those
didn't respect availability annotations, causing us to incorrectly
choose an unavailable operator when available options exist.
Fixes rdar://problem/31592529.
There were various problems with layout constraints either
being ignored or handled incorrectly. Now that I've exercised
this support with an upcoming patch, there are some fixes
here.
Also, introduce a new ExistentialLayout::getLayoutConstriant()
which returns a value for existentials which are class-constrained
but don't have a superclass or any class-constrained protocols;
an example would be AnyObject, or AnyObject & P for some
non-class protocol P.
NFC for now, since these layout-constrained existentials cannot
be constructed yet.
This is an initial implementation of the constraint propagation pass,
disabled by default at the moment as it does not currently pass all
tests.
I have other changes that I'll hold off on for now because they are
incomplete. Without those changes, this pass doesn't really achieve
much, so this is really just a checkpoint on some progress and not
something really worth trying out at this point.
As solveRec() already does, exit immediately if we have a failed
constraint from constraint generation. Not doing so means that we can
create a SolverScope in constraint propagation, and on destruction of
that SolverScope we clear out the failedConstraint field, obscuring the
fact that we had a failure.