These will be used for unit-testing the Type::join functionality in the
type checker. The result of the join is replaced during constraint
generation with the actual type.
There is currently no checking for whether the arguments can be used to
statically compute the value, so bad things will likely happen if
e.g. they are type variables. Once more of the basic functionality of
Type::join is working I'll make this a bit more bullet-proof in that
regard.
They include:
// Compute the join of T and U and return the metatype of that type.
Builtin.type_join<T, U, V>(_: T.Type, _: U.Type) -> V.Type
// Compute the join of &T and U and return the metatype of that type.
Builtin.type_join_inout<T, U, V>(_: inout T, _: U.Type) -> V.Type
// Compute the join of T.Type and U.Type and return that type.
Builtin.type_join_meta<T, U, V>(_: T.Type, _: U.Type) -> V.Type
I've added a couple simple tests to start off, based on what currently
works (aka doesn't cause an assert, crash, etc.).
These helpers are all about trying to decide if a particular overload
is "favored", but the answer won't change if a local archetype is
actually the type we're looking for, so there's no advantage to using
contextual types over interface types. On top of that, the calls to
mapTypeIntoContext are forcing the deserialization of several generic
environments that would have otherwise been left untouched, resulting
in unnecessary calls to the generic signature builder.
This isn't a recent change, but we're seeing strain around the generic
signature builder and complex constraints in the standard library
anyway, so we'll take wins where we can get them.
Discovered as part of the performance investigation in
rdar://problem/33984386.
`LinkedExprAnalyzer` is not always precise in collecting types of expressions,
so let's not try to impose anything upon linked operator expressions, which are
"mergable", except actually merging argument/result types together to help
constraint solver.
Resolves: rdar://problem/27700622
A generic signature like <T : SomeClass> would create
a subtype constraint between the type variable for T and
SomeClass. This is too loose, because a subclass existential
like 'SomeClass & SomeProto' is a subtype of SomeClass, but
cannot bind to T, because it is not representationally a
single retainable pointer.
Fixes <rdar://problem/32617814>, <https://bugs.swift.org/browse/SR-5142>.
Also, begin to pass around base types instead of raw InOutType types. Ideally, only Sema needs to deal with them, but this means that a bunch of callers need to unwrap any inouts that might still be lying around before forming these types.
Multiple parts of the compiler were slicing, dicing, or just dropping these flags. Because I intend to use them for the new function type representation, I need them to be preserved all across the compiler. As a first pass, this stubs in what will eventually be structural rules as asserts and tracks down all callers of consequence to conform to the new invariants.
This is temporary.
Special DeclNames represent names that do not have an identifier in the
surface language. This implies serializing the information about whether
a name is special together with its identifier (if it is not special)
in both the module file and the swift lookup table.
When re-typechecking an expression during diagnostics, we begin by
erasing all the types in the expression. However, any expressions
created as part of applying the solution will remain.
CSGen was doing the wrong thing when it encountered EnumIsCaseExpr,
which can only appear in already-type checked ASTs.
Returning expr->getType() is not correct, because the type is not
yet set; returning a null type is intended to signal that a
diagnostic was already emitted, which causes Sema to stop
type checking.
The end result is that certain combinations of invalid code with
an 'is' cast nested inside would crash either the AST verifier
(with asserts on) or in SILGen (with asserts off), because we
would stop trying to diagnose the issue prematurely, and possibly
not emit a diagnostic at all.
Fixes <https://bugs.swift.org/browse/SR-5050> and
<rdar://problem/32487948>.
More updates to read and write types from a side table in the constraint
solver and only write back into expressions when we've finished type
checking an expression.
We still write directly into expressions, and will continue to do so
until all of the code has been updated.
With the introduction of special decl names, `Identifier getName()` on
`ValueDecl` will be removed and pushed down to nominal declarations
whose name is guaranteed not to be special. Prepare for this by calling
to `DeclBaseName getBaseName()` instead where appropriate.
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.
And make an attempt to use the constraint system's contextualType to bind type information; this makes things better but doesn't seem to be a complete solution for contextually typing key paths.
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.
It's particularly likely someone will try to type `\(foo)`, which looks like a string interpolation segment, outside of a string literal, so give that case a special diagnostic. Fixes rdar://problem/32315365.
Teach preCheckExpression() about UnresolvedSpecializeExpr
where the base is a TypeExpr.
This allows us to type check expressions like
'[Outer<T>.Inner<U>]()' by folding them down to a TypeExpr
with an array type.
This is a bit more robust and user-friendly than hoping more brittle recovery in SILGen or IRGen for unsupported components kicks in. rdar://problem/32200714
The "common return type" optimization that occurs at
constraint-generation time was overly complicated and wrong in a
couple of places. Fix up these issues:
* Don't cache information about this optimization in the decls
themselves; it ignores visibility as well as invalidation that
occurs in script mode and playgrounds. Just do the the work again
* Don't map type into context; we can bail out when there are type
parameters present
* Skip the "self" parameters of operators in types (since this only
ever occurs for operators).
Longer term, this optimization should move into the solver itself. But
for now, at least it's cleaner/more correct.
An early optimization in constraint generation attempted to simplify
type construction (e.g., X(...)) when the type in question has no
failable initializers. However, the optimization didn't appropriately
clear out the cached bit when new information became available (e.g.,
new conformances, new extensions), and didn't seem to help anything
performance-wise (type-checking times didn't increase at all when I
turned this off).
Fixes rdar://problem/30588177.
This prevents one invalid declaration from causing cascades of subsequent errors.
Fixes:
* test/NameBinding/scope_map_lookup.swift
* test/decl/var/variables.swift
CSGen can see an AssignExpr where the destination has an
unresolved type, even in a case where no diagnostic has been
emitted yet.
It is then wrong to return an empty type from here, because
this stops us from attempting to solve the expression, which
results in no diagnostic being emitted in the end.
The test case I added produces a decent diagnostic now,
but the original one in the radar now just says 'ambiguous
without more context'. Still, better than crashing.
Fixes <rdar://problem/30685195>.
This introduces a few unfortunate things because the syntax is awkward.
In particular, the period and following token in \.[a], \.? and \.! are
token sequences that don't appear anywhere else in Swift, and so need
special handling. This is somewhat compounded by \foo.bar.baz possibly
being \(foo).bar.baz or \(foo.bar).baz (parens around the type), and,
furthermore, needing to distinguish \Foo?.bar from \Foo.?bar.
rdar://problem/31724243
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.
When creating disjunctions with favored constraints in constraint
optimization, we actually ended up duplicating the constraint that we
favor, resulting with extra constraints in the disjunction.
Noticed while debugging other issues.
TODO:
- Select the KeyPath subclass corresponding to the write capability of the key path components
- Figure out an issue with unresolved solutions being chosen with contextually-typed keypaths
- Diagnostic QoI