We use simplifyConstraint() to activate other constraints, and then
examine those constraints to find related disjunctions. In examining
those active constraints, we were simplifying them in case they
failed (which would allow us to bail out earlier). In doing so, we could
potentially generate new disjunctions when we simplify an unresolved
value member constraint. If we do that, we end up collecting these new
disjunctions as part of the set of related disjunctions, but that's
problematic because as part of exiting the solver scope to roll back
changes we delete these disjunctions from the system.
Instead of actually simplifying the active constraints, just collect the
disjunctions and move the active constraints back to the inactive list.
With this change we can build the stdlib.
This is still disabled by default, and as with the previous
implementation does not pass all tests if enabled.
Rather than looking for applicable function constraints and then looking
at the bind overload disjunctions associated with those, instead
directly collect all bind overload disjunctions and revise the enabled
elements of those disjunctions by attempting to bind them simultaneously
with the elements of other disjunctions that are linked to this one
through applicable function constraints.
Don't pass in the opened type; instead have the caller call
simplifyType() if needed. Also, make computeSubstitutions()
bail out if there's no generic signature, which allowed
unifying several generic vs non-generic code paths.
Hopefully there is enough short circuiting in there now that
we're not doing any extra work in the non-generic case.
There are a handful of things, but the primary ones are that we really
don't want to track depth of recursion so much as whether we are
processing at the "top level" of constraints we're looking at or not so
that we can determine whether we can disable elements from a
disjunction.
Related, there are places where we can bail out earlier if we know
that *any* neighboring constraint passes.
Also updating the way we gather neighboring constraints to be
independent of the function that simplifies them. The original code was
wrong in that in bailed as soon as one of the simplifications
failed (which meant we might not gather all of them).
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.
This is disabled by default but enabled under the frontend option
-propagate-constraints.
The idea here is to have a pass that enforces local consistency in our
constraint system, in order to reduce the domains of constraint
variables, speeding up the solving of the constraint system.
The initial focus will be on reducing the size of the disjunctions for
function overloads with the hope that it substantially improves the
performance of type checking many expressions.
We previously penalized bindings to Any, and that resulted in
inappropriately rejecting solutions where we bind a decl that is
explicitly typed Any. That penalty was removed in
170dc8acd7, but that has led to a variety
of source compatibility issues.
So now, we'll reintroduce a penalty for Any-typed things, but instead of
penalizing bindings (which happen both because of explicitly-typed
values in the source, and implicitly due to attempting various types for
a particular type variable), penalize casts, which are always present in
some form in the source.
Thanks go to John for the suggestion.
Fixes
SR-3817 (aka rdar://problem/30311052)
SR-3786 (aka rdar://problem/30268529)
rdar://problem/29907555
Without this, CSGen/CSSimplify and CSApply may have differing
opinions about whether e.g. a let property is settable, which
can lead to invalid ASTs.
Arguably, a better fix would be to remove the dependency on the
exact nested DC. For example, we could treat lets as settable
in all contexts and then just complain later about invalid
attempts to set them. Or we could change CSApply to directly
use the information it already has about how an l-value is used,
rather than trying to figure out whether it *might* be getting set.
But somehow, tracking a new piece of information through the
entire constraint system seems to be the more minimal change.
Fixes rdar://29810997.
ConstraintSystem::simplifyType() replaced types with their fixed types
from the global map.
Solution::simplifyType() replaced types with their fixed types from the
current bindings.
There were some minor differences between the two, and some dead code.
Rather than waiting until we've used a huge amount of memory, attempt to
make the choice to bail out based on the number of type bindings /
disjunction choices we visit.
I expect this will generally fail faster than the Swift 3 metric, but
will still only fail when we've got clearly exponential type checking
behvior.
Since we have multiple sources of exponential behavior today, I don't
want to make the bounds too tight. Once we fix some/most of that
behavior we can look at further tightening up the metric.
Several fixes in order to make handling of types more consistent.
In particular:
- Expression types used within the constraint system itself always use
the type map.
- Prior to calling out to any TypeChecker functions, the types are
written back into the expression tree. After the call, the types are
read back into the constraint system type map.
- Some calls to directly set types on the expressions are reintroduced
in places they make sense (e.g. when building up new expressions that
are then passed to typeCheckExpressionShallow).
ConstraintSystem::setType() is still setting the type on the expression
nodes at the moment, because there is still some incorrect handling of
types that I need to track down (in particular some issues related to
closures do not appear to be handled correctly). Similarly, when we
cache the types in the constraint system map, we are not clearing them
from the expression tree yet.
The diagnostics have not been updated at all to use the types from
the constraint system where appropriate, and that will need to happen as
well before we can remove the write from ConstraintSystem::setType()
into the expression and enable the clearing of the expression tree type
when we cache it in the constraint system.
These are used from within constraint system code, and for those uses we
need to be reading from the constraint system type map.
Add the parallel constraint system interfaces that call into the
Expr interfaces with the appropriate accessors.
withoutActuallyEscaping has a signature like `<T..., U, V, W> (@nonescaping (T...) throws<U> -> V, (@escaping (T...) throws<U> -> V) -> W) -> W, but our type system for functions unfortunately isn't quite that expressive yet, so we need to special-case it. Set up the necessary type system when resolving an overload set to reference withoutActuallyEscaping, and if a type check succeeds, build a MakeTemporarilyEscapableExpr to represent it in the type-checked AST.
The prior formulation of bridging conversions allowed conversion to
more-optional types, e.g., converting an "NSDate" to "Date?", which
was broken by my recent refactoring in this area. Allow bridging
conversions to more-optional types by introducing extra optional
injections at the end.
Fixes rdar://problem/29780527.
Previously, bridging conversions were handled as a form of "explicit
conversion" that was treated along the same path as normal
conversions in matchTypes(). Historically, this made some
sense---bridging was just another form of conversion---however, Swift
now separates out bridging into a different kind of conversion that is
available only via an explicit "as". This change accomplishes a few
things:
* Improves type inference around "as" coercions. We were incorrectly
inferring type variables of the "x" in "x as T" in cases where a
bridging conversion was expected, which cause some type inference
failures (e.g., the SR-3319 regression).
* Detangles checking for bridging conversions from other conversions,
so it's easier to isolate when we're applying a bridging
conversion.
* Explicitly handle optionals when dealing with bridging conversions,
addressing a number of problems with incorrect diagnostics, e.g.,
complains about "unrelated type" cast failures that would succeed at
runtime.
Addresses rdar://problem/29496775 / SR-3319 / SR-2365.
Follow the pattern set by isDictionaryType() of performing the query
and extracting the underlying key/element types directly. We often
need both regardless. NFC
We currently have an element in the solution score related to whether we
had a binding or equality constraint involving Any.
Doing this yields some strange results, e.g. if overload resolution
results in a property declared as Any we end up discarding that solution
in favor of solutions that involve other overloads that are not declared
as Any but are also not actually better solutions (e.g. overloads that
are declared as function types).
We really want to retain both solutions in this case and allow the
ranking step of the solver to decide on the better choice.
Fixes rdar://problem/29374163, rdar://problem/29691909.
This parameter implements getType() for the given expression, making
it possible to use this from within the constraint system, which now
has it's own side map for types of expressions.
Switch ConstraintSystem::getType() to returning the type from the
constraint system type map.
For now, assert that these types equal the types in the expression
nodes since we are still setting the expression node types in
ConstraintSystem::setType().
Instead of relying on the SolverScope to rollback all of the changes
done to constraints in the system at the end of its life time, move
all of the logic handling that into SolverState where retired/generated
constraints live.
Since retired constraints are re-added back to the circulation in LIFO
order, make sure that all of the constraints are added to the front of
SolverScope::retiredConstraints list.
Update CSGen/CSApply/CSSolver to primarily use getType() from
ConstraintSystem.
Currently getType() just returns the type on the expression. As with
setType(), which continues to set the type on the expression, this
will be updated once all the other changes are in place.
This change also moves coerceToRValue from TypeChecker to
CosntraintSystem so that it can access the expression type map in the
constraint system.
I've been unable to reproduce the issue that hit on the builder, and
still expect this change to be NFC, so trying it out again. If it
fails, I'll revert again and try another shot at reproducing.
Original commit message:
We create new expressions that have the type on the expression
set. Make sure we capture these types in the constraint system type
map so that we can refer to types uniformally by consulting the map.
NFC.
(cherry picked from commit 57d5d974ff)