Previously we recorded the canonical type of the declaration and made
sure we could deserialize that, but that's a lot of extra work
building up intermediate types that we mostly don't need. Instead,
record smaller types that represent the possible points of failure---
right now, just the nominal types that are referenced by the value
(function, variable/constant, subscript, or initializer). I chose to
use types instead of declarations here because types can potentially
encode more complicated constraints later (such as generic types
checking that their arguments still conform).
This gains us back 20% of type-checking time on a compile-time
microbenchmark: `let _ = [1, 2]`. I expect the effect is less dramatic
the more expressions you have, since we only need to deserialize
things once.
Fixes a class of deserialization issues in the merge-modules
step.
The setup was the following:
- File A defines a typealias A whose underlying type is a nested
type S of a type T, defined in a different module.
- File B defines an extension of T, and the extension member's
type references A.
When deserializing A, we would proceed to deserialize the
underlying type, which references T.S. This would first deserialize
T and perform a name lookup to find S, which would deserialize all
members, including pulling in extensions. Deserialization of the
extension defined in file B would then fail, because the declaration
for A is not yet available.
We had a previous fix for these problems in the single-module case;
a per-file lookup table mapping mangled nested type names to
declarations, allowing a nested type to be deserialized without
pulling in all members and extensions of its parent type.
This patch generalizes the nested type lookup table allowing it to
be used to resolve cross-module references as well. Also, we were
only writing out the nested type table when serializing a partial
swiftmodule corresponding to a source file. Removing this check
allows the nested type table to be serialized for modules built
with WMO enabled as well, such as the standard library.
Fixes <rdar://problem/30976604> and
<https://bugs.swift.org/browse/SR-4208>.
As such, we no longer insert two placeholders for initializers that
need two vtable slots; instead we record that in the
MissingMemberDecl. I can see MissingMemberDecl growing to be something
we'd actually show to users, that can be used for other kinds of
declarations that don't have vtable entries, but for now I'm not going
to worry about any of that.
That is, whether an initializer is 'required', and either does not
override anything or overrides a non-required initializer. We don't
use this for anything now, but it'll show up in the next commit.
Replace `NameOfType foo = dyn_cast<NameOfType>(bar)` with DRY version `auto foo = dyn_cast<NameOfType>(bar)`.
The DRY auto version is by far the dominant form already used in the repo, so this PR merely brings the exceptional cases (redundant repetition form) in line with the dominant form (auto form).
See the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es11-use-auto-to-avoid-redundant-repetition-of-type-names) for a general discussion on why to use `auto` to avoid redundant repetition of type names.
This lets us serialize that decision, which means we can conceivably
/change/ the decision in later versions of the compiler without
breaking existing code. More immediately, it's groundwork that will
eventually allow us to drop decls from the AST without affecting
vtable layout.
This isn't actually a great answer; what we really want is for SIL
vtables to be serialized consistently and treated as the point of
truth. But that would be more change than we're comfortable taking in
the Swift 4 timeframe.
First part of rdar://problem/31878396.
This attribute allows one to provide the "legacy" name of a class for
the purposes of archival (via NSCoding). At the moment, it is only
useful for suppressing the warnings/errors about classes with unstable
archiving names.
Proof-of-concept for the above. This shouldn't be common---renames are
far more likely, and those we can track---but occurs when the
swift_wrapper attribute (the implementation of NS_STRING_ENUM) is
active in Swift 4 but not in Swift 3.
Note that this only checks the canonical interface type of the
declaration, because the non-canonical type may contain references to
the declaration's generic parameters.
In order to accomplish this, cross-module references to typealiases
are now banned except from within conformances and NameAliasTypes, the
latter of which records the canonical type to determine if the
typealias has changed. For conformances, we don't have a good way to
check if the typealias has changed without trying to map it into
context, but that's all right---the rest of the compiler can already
fall back to the canonical type.
Module files store all of the Objective-C method entrypoints in a
central table indexed by selector, then filter the results based on
the specific class being requested. Rather than storing the class as
a TypeID---which requires a bunch of deserialization---store its
mangled name. This allows us to deserialize less, and causes circular
deserialization in rdar://problem/31615640.
Add a 'hasExplicitAnyObject()' bit to ProtocolCompositionType
to represent canonical composition types containing '& AnyObject'.
Serialize this bit and take it into account when building
ExistentialLayouts.
Rename ProtocolCompositionType::getProtocols() to getMembers()
since it can contain classes now, and update a few usages that
need further attention with FIXMEs or asserts.
For now, nothing actually constructs these types, and they will
trigger arounds asserts. Upcoming patches will introduce support
for this.
That is, a Swift 3 target imported into a Swift 4 context or vice
versa. This requires serializing the compatibility mode explicitly,
instead of including it in the textual version string that's only
for debugging.
All of this information is recoverable from the more-general,
more-sane signature conformances, so stop
recording/serializing/deserializing all of this extra stuff.
Filter out any -ivfsoverlay options that include an
unextended-module-overlay.yaml overlay. By convention the Xcode
buildsystem uses these while *building* mixed Objective-C and Swift
frameworks; but they should never be used to *import* the module
defined in the framework.
rdar://problem/30934351
ExtensionDecls for nested generic types have multiple generic parameter
lists, one for each level of nested generic context.
We only serialized the outermost list, though. This didn't cause any
problems as far as I can see because most of the time we seem to use
the GenericSignature instead, which has the correct generic parameters.
However since we still have usages of getGenericParamsOfContext() on
deserialized DeclContexts, better safe than sorry.
I added a test; the test used to pass on master, but with the new
assertion I added, it would fail without the other changes in this
patch.
A lot of files transitively include Expr.h, because it was
included from SILInstruction.h, SILLocation.h and SILDeclRef.h.
However in reality most of these files don't do anything
with Exprs, especially not anything in IRGen or the SILOptimizer.
Now we're down to 171 files in the frontend which depend on
Expr.h, which is still a lot but much better than before.
This was a remnant of the old generics implementation, where
all nested types were expanded into an AllArchetypes list.
For quite some time, this method no longer returned *all*
dependent types, only those with generic requirements on
them, and all if its remaining uses were a bit convoluted.
- In the generic specialization code, we used this to mangle
substitutions for generic parameters that are not subject
to a concrete same-type constraint.
A new GenericSignature::getSubstitutableParams()
function handles this use-case instead. It is similar
to getGenericParams(), but only returns generic parameters
which require substitution.
In the future, SubstitutionLists will only store replacement
types for these generic parameters, instead of the list of
types that we used to produce from getAllDependentTypes().
- In specialization mangling and speculative devirtualization,
we relied on SubstitutionLists having the same size and
order as getAllDependentTypes(). It's better to turn the
SubstitutionList into a SubstitutionMap instead, and do lookups
into the map.
- In the SIL parser, we were making a pass over the generic
requirements before looking at getAllDependentTypes();
enumeratePairedRequirements() gives the correct information
upfront.
- In SIL box serialization, we don't serialize the size of the
substitution list, since it's available from the generic
signature. Add a GenericSignature::getSubstitutionListSize()
method, but that will go away soon once SubstitionList
serialization only serializes replacement types for generic
parameters.
- A few remaining uses now call enumeratePairedRequirements()
directly.
The protocol conformance checker verifies that all of the requirements
in the protocol's requirement signature are fulfilled. Save the
conformances from that check into the NormalProtocolConformance,
because this is the record of how that concrete type satisfies the
protocol requirements.
Compute, deserialize, and verify this information, but don't use it
for anything just yet. We'll use this to eliminate the "inherited
protocol map" and possibility some redundant type-witness
information.
Replace an existing flag for cross-references to member types (that
wasn't getting much use) with one consistent with how we lookup
values. This fixes the case where someone actually has a useful type
as a member of a protocol extension, and that type gets referenced in
another module; Dispatch does exactly this.
Because you can currently only define typealiases in protocol
extensions, not new types, there's always a workaround for someone
hitting this issue: just use the underlying type.
https://bugs.swift.org/browse/SR-4076
The list of directly inherited protocols of a ProtocolDecl is already
encoded in the requirement signature, as conformance constraints where
the subject is Self. Gather the list from there rather than separately
computing/storing the list of "inherited protocols".
This has the effect of propagating the search path to the clang importer as '-iframework'.
It doesn't affect whether a swift module is treated as system or not, this can be done as follow-up enhancement.
Previously looking up an extension would result in all extensions for
types with the same name (nested or not) being deserialized; this
could even bring in base types that had not been deserialized yet. Add
in a string to distinguish an extension's base type; in the top-level
case this is just a module name, but for nested types it's a full
mangled name.
This is a little heavier than I'd like it to be, since it means we
mangle names and then throw them away, and since it means there's a
whole bunch of extra string data in the module just for uniquely
identifying a declaration. But it's correct, and does less work than
before, and fixes a circularity issue with a nested type A.B.A that
apparently used to work.
https://bugs.swift.org/browse/SR-3915