Since `ConstraintSystem::shrink` is going to attempt to type-check
sub-expressions separately it's essential to clean-up AST if constraint
generation or solving of the such expressions fails, otherwise if
such solving resulted in creation of implicit expression type variables
might leak to the outside.
This commit introduces new kind of requirements: layout requirements.
This kind of requirements allows to expose that a type should satisfy certain layout properties, e.g. it should be a trivial type, have a given size and alignment, etc.
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.
We were only reporting it in cases where we found no solutions before
deciding the expression was too complex. Had we found some solution, we
would go ahead and use that solution before bailing out due to
complexity, which means e.g. we might have been allowing otherwise
ambiguous expression to type check.
Checked casts are dependent on run-time queries; we should not attempt
to infer type variable bindings from them, because doing so produces
unreasonable bindings. Fixes rdar://problem/29894174.
This gives us much better diagnostics around things like
escaping-mismatched function parameters which would previously skip
this and produce bogus invalid conversion errors between “identical”
types.
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.
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.
Changes:
* Terminate all namespaces with the correct closing comment.
* Make sure argument names in comments match the corresponding parameter name.
* Remove redundant get() calls on smart pointers.
* Prefer using "override" or "final" instead of "virtual". Remove "virtual" where appropriate.
Once we've bound a type variable, we find those inactive constraints
that mention the type variable and make them active, so they'll be
simplified again. However, we weren't finding *all* constraints that
could be affected---in particular, we weren't searching everything
related to the type variables in the equivalence class, which meant
that some constraints would not get visited... and we would to
type-check simply because we didn't look at a constraint again when we
should have.
Fixes rdar://problem/29633747.
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.
Make SolverState manage whether the ConstraintSystem it belongs to has a
current SolverState.
Also a couple minor formatting fixes for ternary expressions involving
solverState.
Simplify some control-flow to reduce indentation and eliminate an
unneeded flag variable.
Also update a comment to match the code that went in with
b5500b8600.
The constraint solver tries not to solve for type variables that
"involve other type variables", which handles the case where we have
seen a constraint that mentions the type variable under consideration
as well as a different type variable, but in a constraint that we
cannot capture in a binding. Solving for such type variables too early
can lead to missed solutions, so we avoid it.
Tweak the logic for this computation to not consider type variables
mentioned within dependent member types (e.g., $T0.Iterator.Element),
because such types do not affect type inference at all, and therefore
shouldn't prevent solving for the type variable in question.
In the constraint solver, we've traditionally modeled nested type via
a "type member" constraint of the form
$T1 = $T0.NameOfTypeMember
and treated $T1 as a type variable. While the solver did generally try
to avoid attempting bindings for $T1 (it would wait until $T0 was
bound, which solves the constraint), on occasion we would get weird
behavior because the solver did try to bind the type
variable.
With this commit, model nested types via DependentMemberType, the same
way we handle (e.g.) the nested type of a generic type parameter. This
solution maintains more information (e.g., we know specifically which
associated type we're referring to), fits in better with the type
system (we know how to deal with dependent members throughout the type
checker, AST, and so on), and is easier to reason able.
This change is a performance optimization for the type checker for a
few reasons. First, it reduces the number of type variables we need to
deal with significantly (we create half as many type variables while
type checking the standard library), and the solver scales poorly with
the number of type variables because it visits all of the
as-yet-unbound type variables at each solving step. Second, it
eliminates a number of redundant by-name lookups in cases where we
already know which associated type we want.
Overall, this change provides a 25% speedup when type-checking the
standard library.
At one point this was added in order to inhibit some bridging
conversions while we are handling favored constraints, but that code has
been removed now, making this dead.
Noticed by inspection.
When a constraint fails, we retire it... but we also need to remove it
from the constraint graph. Otherwise, we break invariants when
diagnostic generation attempts to continue simplification.
Fixes rdar://rdar28145033.
Found by inspection; a misplaced 'break' meant that, if we encountered
a relational constraint where both sides are type variables that are
equivalent, we would stop looking for more type bindings, which could
lead us to miss obvious type inferences. While I wasn't able to
construct a case where this changed the behavior of type inference,
this *does* happen, and the previous code was clearly wrong.
We previously allowed *any* conformance constraint to an
ExpressibleBy*Literal protocol to provide a default type (e.g.,
Int/Double/String/etc.) based on the kind of literal protocol. This
led to weird type inference behavior. Restrict the defaulting to
actual literals---not just conformances to literal protocols---which
is a much more reasonable rule.
Because this is a source-breaking change, only introduce this new
behavior when the Swift version >= 4, maintaining the old behavior in
Swift 3 compatibility mode.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).
(cherry picked from commit 6bdd9cfae5)
This reverts commit 6bdd9cfae5. This
commit *appears* to be breaking something in Dollar involving
inference with array literals and 'nil'; pull it back for more
investigation.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).
While, tracking defaulted constraints based on their type variable
usually works in practice, it can break if the type variable ends up
being equivalent to some other type variable that. Instead, record the
locators associated with Defaultable constraints where we used the
default, which are easier to work with during constraint application.
We had a few places that were performing ad hoc variants of
ConstraintSystem::getFixedTypeRecursive(); simplify it's interface so
we can use it everywhere consistently. Fixes rdar://problem/27261929.
In most places where we were checking "is<ErrorType>()", we now mean
"any error occurred". The few exceptions are in associated type
inference, code completion, and expression diagnostics, where we might
still work with partial errors.