Conformance manglings, which are used for witness tables and related witness
thunks, mangle the generic signature of the conformance. Since conformances
also describe the conforming type, mangle the conformances's generic signature
relative to the conforming type's generic signature.
In practice, this means that we don't mangle any part of the generic signature
into a conformance mangling now, so we see a decent win: 2.3% smaller
trie and 6.4% smaller strings section in the standard library binary.
When conditional conformances land, we'll see some generic signatures
mangling again (for the additional requirements of the constrained
extension).
We used to give witness thunks public linkage if the
conforming type and the protocol are public.
This is completely unnecessary. If the conformance is
fragile, the thunk should be [shared] [serialized],
allowing the thunk to be serialized into callers after
devirtualization.
Otherwise for private protocols or resilient modules,
witness thunks can just always be private.
This should reduce the size of compiled binaries.
There are two other mildly interesting consequences:
1) In the bridged cast tests, we now inline the witness
thunks from the bridgeable conformances, which removes
one level of indirection.
2) This uncovered a flaw in our accessibility checking
model. Usually, we reject a witness that is less
visible than the protocol; however, we fail to
reject it in the case that it comes from an
extension.
This is because members of an extension can be
declared 'public' even if the extended type is not
public, and it appears that in this case the 'public'
keyword has no effect.
I would prefer it if a) 'public' generated a warning
here, and b) the conformance also generated a warning.
In Swift 4 mode, we could then make this kind of
sillyness into an error. But for now, live with the
broken behavior, and add a test to exercise it to ensure
we don't crash.
There are other places where this "allow public but
ignore it, kinda, except respect it in some places"
behavior causes problems. I don't know if it was intentional
or just emergent behavior from general messiness in Sema.
3) In the TBD code, there is one less 'failure' because now
that witness thunks are no longer public, TBDGen does not
need to reason about them (except for the case #2 above,
which will probably require a similar workaround in TBDGen
as what I put into SILGen).
Instead of appending a character for each substitution, we now prefix the substitution with the repeat count, e.g.
AbbbbB -> A5B
The same is done for known-type substitutions, e.g.
SiSiSi -> S3i
This significantly shrinks mangled names which contain large lists of the same type, like
func foo(_ x: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int))
rdar://problem/30707433
Reimplement the witness matching logic used for generic requirements
so that it properly models the expectations required of the witness,
then captures the results in the AST. The new approach has a number of
advantages over the existing hacks:
* The constraint solver no longer requires hacks to try to tangle
together the innermost archetypes from the requirement with the
outer archetypes of the context of the protocol
conformance. Instead, we create a synthetic set of archetypes that
describes the requirement as it should be matched against
witnesses. This eliminates the infamous 'SelfTypeVar' hack.
* The type checker no longer records substitutions involving a weird
mix of archetypes from different contexts (see above), so it's
actually plausible to reason about the substitutions of a witness. A
new `Witness` class contains the declaration, substitutions, and all
other information required to interpret the witness.
* SILGen now uses the substitution information for witnesses when
building witness thunks, rather than computing all of it from
scratch. ``substSelfTypeIntoProtocolRequirementType()` is now gone
(absorbed into the type checker, and improved from there), and the
witness-thunk emission code is simpler. A few other bits of SILGen
got simpler because the substitutions can now be trusted.
* Witness matching and thunk generation involving generic requirements
and nested generics now works, based on some work @slavapestov was
already doing in this area.
* The AST verifier can now verify the archetypes that occur in witness substitutions.
* Although it's not in this commit, the `Witness` structure is
suitable for complete (de-)serialization, unlike the weird mix of
archetypes previously present.
Fixes rdar://problem/24079818 and cleans up an area that's been messy
and poorly understood for a very, very long time.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
And include some supplementary mangling changes:
- Give the first generic param (depth=0, index=0) a single character mangling. Even after removing the self type from method declaration types, 'Self' still shows up very frequently in protocol requirement signatures.
- Fix the mangling of generic parameter counts to elide the count when there's only one parameter at the starting depth of the mangling.
Together these carve another 154KB out of a debug standard library. There's some awkwardness in demangled strings that I'll clean up in subsequent commits; since decl types now only mangle the number of generic params at their own depth, it's context-dependent what depths those represent, which we get wrong now. Currying markers are also wrong, but since free function currying is going away, we can mangle the partial application thunks in different ways.
Swift SVN r32896
Canonical dependent member types are always based from a generic parameter, so we can use a more optimal mangling that assumes this. We can also introduce substitutions for AssociatedTypeDecls, and when a generic parameter in a signature is constrained by a single protocol, we can leave that protocol qualification out of the unsubstituted associated type mangling. These optimizations together shrink the standard library by 117KB, and bring the length of the longest Swift symbol in the stdlib down from 578 to 334 characters, shorter than the longest C++ symbol in the stdlib.
Swift SVN r32786
'Ss' appears in manglings tens of thousands of times in the standard library and is also incredibly frequent in other modules. This alone is enough to shrink the standard library by 59KB.
Swift SVN r32409