This is accomplished by recognizing this specific situation and
replacing the 'objc' attribute with a hidden '_objcRuntimeName'
attribute. This /only/ applies to classes that are themselves
non-generic (including any enclosing generic context) but that have
generic ancestry, and thus cannot be exposed directly to Objective-C.
This commit also eliminates '@NSKeyedArchiverClassName'. It was
decided that the distinction between '@NSKeyedArchiverClassName' and
'@objc' was too subtle to be worth explaining to developers, and that
any case where you'd use '@NSKeyedArchiverClassName' was already a
place where the ObjC name wasn't visible at compile time.
This commit does not update diagnostics to reflect this change; we're
going to change them anyway.
rdar://problem/32414557
Layout for an enum depends very intimately on its cases---both their
existence and what their payload types are. That means there's no way
to "partly" recover from failure to deserialize an individual case's
payload type, the way we can partly recover from failing to
deserialize an initializer in a class. Add deserialization recovery
to enums by validating all of their payload types up front, and
dropping the enum if we can't import all of the cases.
This is the first time where we're trying to do deserialization
recovery for a /type/, and that could have many more ripple effects
than for a var/func/subscript/init. A better answer here might be to
still import the enum but mark it as unavailable, but in that case
we'd have to make sure to propagate that unavailability to anything
that /used/ the enum as well. (In Swift, availability is checked based
on use of the name, so if someone manages to refer to an enum using
inferred types we'd be in trouble.)
There is one case here that's not covered: if an enum case has a
payload that references a type declaration nested within the enum, but
then that nested type /itself/ can't be loaded for some reason, we
have no way to check that up front, because we can't even try to load
the nested type without loading its parent DeclContext (the enum). I
can't think of an easy solution for this right now.
(In the future, we'll be able to support dropping a single case for
resilient enums. But we're not there right now.)
rdar://problem/31920901
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.
Make generic environment deserialization lazy, which eliminates a
significant amount of up-front work. Most clients only need the
generic signature, not the full generic environment.
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.
Deserializing a witness record in a conformance may fail if either of the requirement or witness changed name or type, most likely due to SDK modernization changes across Swift versions. When this happens, leave an opaque placeholder in the conformance to indicate that the witness exists but we don't get to see it. For expedience, right now this just witnesses the requirement to itself, so that code in the type checker or elsewhere that tries to ad-hoc devirtualize references to the requirement just gets the requirement back. Arguably, we shouldn't include the witness at all in imported conformances, since they should be an implementation detail, but that's a bigger, riskier change. This patch as is should be enough to address rdar://problem/31185053.
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.
Like the previous commit, but with added trickiness because we also
serialize the form of the PatternBindingDecl a property came from.
Make getPattern handle a failure in the simple case that overrides
use, and pass that up to the PatternBindingDecl initialization. (This
can result in zero-element PatternBindingDecls, but that's fine.)
'getPattern' is also a change from 'maybeGetPattern', but every caller
knows how many patterns it expects, so accomodating the "maybe" case
is no longer important.
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.
Previously we would drop all serialized SIL from partial swiftmodule
files generated while compiling source in non-WMO mode; all that was
missing was linking it in.
This adds a frontend flag, and a test; driver change is coming up
next.
Progress on <rdar://problem/18913977>.
Also, add a third [serializable] state for functions whose bodies we
*can* serialize, but only do so if they're referenced from another
serialized function.
This will be used for bodies synthesized for imported definitions,
such as init(rawValue:), etc, and various thunks, but for now this
change is NFC.
Back in December DougG added code to delay the formation of generic
environments until all declarations from a particular module had been
deserialized, to avoid circular dependencies caused by too-eager
deserialization of protocol members. This worked great for fully-built
modules, but still had some problems with module merging, the phase of
multi-file compilation where the "partial" swiftmodules that
correspond to each source file in a target are loaded and remitted as
a single swiftmodule. Fix this by picking one of the partial
swiftmodules as the representative one for delayed actions, and wait
until deserialization is complete for /all/ of the serialized ASTs in
the same target to form the generic environments.
rdar://problem/30984417
to correctly handle generalized protocol requirements.
The major missing pieces here are that the conformance search
algorithms in both the AST (type substitution) and IRGen
(witness table reference emission) need to be rewritten to
back-track requirement sources, and the AST needs to actually
represent this stuff in NormalProtocolConformances instead
of just doing ???.
The new generality isn't tested yet; I'm looking into that,
but I wanted to get the abstractions in place first.