(currently spelled with an underscore to indicate its WIP state)
Later commits will handle imported enums correctly and implement the
checks for switch cases.
We can encounter these when the compiler modifies an inlinable
function to break apart a struct and the struct uses a private
type for one of its fields. It's questionable whether we /should/
handle this, but meanwhile this /is/ a non-intrusive fix that
preserves the performance of non-resilient libraries.
(That is, it appears this worked in Swift 4.0, though perhaps
not all of the same optimizations kicked in.)
https://bugs.swift.org/browse/SR-6874
This is technically a source break, but the @_fixed_layout attribute
is not official yet. If anyone really cares, we can make this
conditional on -swift-version 5 later, but I'd rather not.
This change is necessary so that we can give property initializers
non-public linkage. Currently they are public, because they can be
referenced from inlinable initializers.
Now that property initializers inside a @_fixed_layout type can
only reference public symbols, they no longer have to be public,
but making that change requires a bit more work.
For now these are underscored attributes, i.e. compiler internal attributes:
@_optimize(speed)
@_optimize(size)
@_optimize(none)
Those attributes override the command-line specified optimization mode for a specific function.
The @_optimize(none) attribute is equivalent to the already existing @_semantics("optimize.sil.never") attribute
When a conformance can either be synthesized or implied, we tend to prefer
implied. However, if the implied conformance comes from a deserialized
conformance, it will lead to an incomplete conformance and cause a crash.
This is a narrow fix for SR-6105 / rdar://problem/34911378.
introduce a common superclass, SILNode.
This is in preparation for allowing instructions to have multiple
results. It is also a somewhat more elegant representation for
instructions that have zero results. Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction. Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.
A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.
Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
This commit contains:
-) adding the new instructions + infrastructure, like parsing, printing, etc.
-) support in IRGen to generate global object-variables (i.e. "heap" objects) which are statically initialized in the data section.
-) IRGen for global_value which lazily initializes the object header and returns a reference to the object.
For details see the documentation of the new instructions in SIL.rst.
This avoids having to bring in all members (and extensions!) for an
outer type just to look up a nested type. In the test case attached
(reduced from the project in SR-5284), this actually led to a circular
dependency between deserialization and the importer, which resulted in
a compiler crash.
This is not a new problem, but it's more important with the release of
Swift 4, where a number of Apple SDK types are now newly imported as
member types. (The one in the original bug was
NSView.AutoresizingMask, formerly NSAutoresizingMaskOptions.) Since we
always use the Swift 4 name for cross-references, this affected
everyone, even those still compiling in Swift 3 mode.
https://bugs.swift.org/browse/SR-5284
There can be a circularity when two enums recur through each other, and deserialization currently is not set up to robustly detect and avoid these circularities. This should avoid regressions, but re-exposes some possible cases that should require recovery in mix-and-match situations. Short-term fix for rdar://problem/32337278.
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>.
There are a number of type witnesses that are introduced by the Clang
importer. Immediately resolve those witnesses *without* going through
the type checker, because there are cases (i.e., deserialized SIL)
where the conformance is created but there is no type checker around.
Fixes rdar://problem/30364905, rdar://problem/31053701,
rdar://problem/31565413 / SR-4565.
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.
This is like a single-threaded variant of the "lost wakeup
problem" that's all too common to anyone who's worked on
concurrent code.
When we perform lookup into a nominal type, we check if the
ASTContext's generation number is different than a cached
generation number in the nominal type. If the two numbers
differ, we walk over all loaded module files, telling them
to load any serialized extensions. Then we update the cached
generation number in the nominal type to record the fact
that we loaded any outstanding extensions.
The idea is to avoid unnecessary work if we know that no new
extensions have been added since the last name lookup.
The "bottom half" here is that when we add a new serialized
module file, we increment the ASTContext's generation number,
and then add an entry for the module file to a list.
The problem was that in between incrementing the ASTContext's
generation number and adding the module file, we would do some
work involving the ClangImporter which could in turn trigger
name lookup, which would "see" the new generation number in
the ASTContext, but not the new thing that is about to be
added, because it hasn't been added yet. So the
NominalTypeDecl's cached generation number would move forward
and the subsequent add of the module file would be "lost".
Specifically, it looks like when SerializedModuleLoader::loadAST()
calls loadedModuleFile->associateWithFileContext(), which does
some crazy ClangImporter stuff I don't understand, which in
turn can trigger a name lookup.
The fix appears to be to bump the generation number *after*
calling associateWithFileContext().
I don't completely understand what went wrong. For example,
this was dependent on the order of 'import' statements in the
input file. Of the two test cases I added, one the first one
triggered the problem -- the other test case is identical,
except the two import statements are transposed. I'm adding it
to ensure we avoid regressing in this case also.
Also I suspect it is possible to construct a test case that
does not depend on Objective-C interop or Foundation, but
again this looked tricky and I don't think the additional test
coverage on Linux would be worth the effort.
Fixes <rdar://problem/30817732>, so RxSwift now builds again on
master. Yay!
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
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.
This is a bit of a hack to dodge an assertion. In essence, it's a
harmless hack, but we'd like to make the handling of optional and
unavailable requirements more rigorous.
This got reverted because it made our non-deterministic deserialization
crasher come up more often. Re-applying this patch to test the theory
that @jrose-apple's fix addressed the issue.
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
When we're looking up all associated types with the same name in order
to find the right archetype anchor, skip extension members to avoid
circular deserialization.
Discovered while investigating <rdar://problem/30248571>.
Once we move to a copy-on-write implementation of existential value buffers we
can no longer consume or destroy values of an opened existential unless the
buffer is uniquely owned.
Therefore we need to track the allowed operation on opened values.
Add qualifiers "mutable_access" and "immutable_access" to open_existential_addr
instructions to indicate the allowed access to the opened value.
Once we move to a copy-on-write implementation, an "open_existential_addr
mutable_access" instruction will ensure unique ownership of the value buffer.
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
Every other declaration kind gets this for free in its interface type,
but properties don't. Just add a bit, it's simple enough.
rdar://problem/30289803
It was checking the wrong predicate, and therefore failing to mark
inherited default arguments as actually being inherited.
While here, explicitly clear out default arguments from non-inherited
cloned parameter lists. I don't think this case can come up today, but
it's better to be correct when we do hit it.
rdar://problem/30167924