Just as with conformances, we can detect that a delayed function
needs to be added to the queue from 'first principles' rather than
walking the ExternalDefinitions list.
This completely eliminates the ExternalDefinitions walk from SILGen,
which has several advantages:
- It fixes a source of quadratic behavior. In batch mode, type checking
produces a list of external definitions shared across all primary
files. Then, SILGen runs once per primary file, building a delayed
emission map every time.
- It allows SILGen to emit external definitions which only come into
existence as a result of lazy conformance checking. Previously,
anything that was added after SILGen performed its walk over the
external definitions list would not be emitted.
Instead of visiting all types in the ExternalDefinitions list and
queuing up their conformances, just emit conformances as needed
when they are first referenced.
In SILGenPattern, we need to be able to unforward cleanups when we explode
tuples. Thus we can't use RValue in SILGenPattern since it may implicitly
explode tuples (which without modifying RValue itself we can not
unforward). This patch removes a specific RValue usage that we can replace with
the use of a ManagedValue instead.
rdar://49903264
ManagedValue::{forward,assign}Into both have the signature SILGenFunction &,
SILLocation, SILValue. For some reason copyInto has SILLocation and SILValue
swapped. This commit standardizes copyInto to match the others.
When applying a solution to a nil literal of Optional type, we would
build a direct reference to Optional<T>.none instead of leaving the
NilLiteralExpr in place, because this would generate more efficient
SIL that avoided the call to the Optional(nilLiteral: ()) witness.
However, a few places in the type checker build type-checked AST, and
they build NilLiteralExpr directly. Moving the peephole to SILGen's
lowering of NilLiteralExpr allows us to simplify generated SIL even
further by eliding an unnecessary metatype value. Furthermore, it
allows SILGen to accept NilLiteralExprs that do not have a
ConcreteDeclRef set, which makes type-checked AST easier to build.
These can be recreated if needed in a client library. To do this, I've
added a new ConformanceLookupKind::NonInherited, which can also be
used elsewhere in the project where we're already filtering out
inherited conformances some other way.
Note that this doesn't drop inherited conformances from the entire
serialized interface, just from the list that a class explicitly
declares. They still get referenced sometimes.
rdar://problem/50541451 and possibly others
The machinery assumes that it will always have a +1 value. I am attempting to do
the minimal fix here for cherry-picking purposes.
There isn't a test case with this commit since the immutable address verifier
(in the next commit) verifies that this is done correctly. The specific test
that will trip is vtable_thunks_reabstraction.swift.
rdar://50212579
The determination of whether a property is memberwise-initialized is
somewhat confused for properties that have synthesized backing properties.
Some clients (Sema/Index) want to see the declared properties, while others
(SILGen) want to see the backing stored properties. Add a flag to
`VarDecl::isMemberwiseInitialized()` to capture this variation.
This utility was defined in Sema, used in Sema and Index, declared in
two headers, and semi- copy-pasted into SILGen. Pull it into
VarDecl::isMemberwiseInitialized() and use it consistently.
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:
- Places that call SILType::isAddressOnly()/isLoadable() now call
the SILFunction overload and not the SILModule one.
- SILFunction's overloads of getTypeLowering() and getLoweredType()
now pass the function's resilience expansion down, instead of
hardcoding ResilienceExpansion::Minimal.
- Various other places with '// FIXME: Expansion' now use a better
resilience expansion.
- A few tests were updated to reflect SILGen's improved code
generation, and some new tests are added to cover more code paths
that previously were uncovered and only manifested themselves as
standard library build failures while I was working on this change.
Previously we would emit an alloc_ref_dynamic followed by a call
of the initializing entry point when calling an @objc dynamic
initializer in a class.
However this is unnecessary now that the allocating entry point
does the right alloc_ref_dynamic.
If the initializer witnesses a protocol requirement, the protocol witness
thunk references the allocating entry point directly, since it has no
vtable entry. For this reason we must use alloc_ref_dynamic and not
alloc_ref to ensure the right type of instance is allocated.
Fixes <rdar://problem/49560721>, <https://bugs.swift.org/browse/SR-10285>.
This is necessary since our func may want to emit conditional code with an early
exit, emitting unused cleanups from the current scope via the function
emitBranchAndCleanups(). If we have not yet created those cleanups, we will
introduce a leak along that path.
rdar://49990484
Sema no longer adds conformances to a per-SourceFile list that it thinks
are going to be "used" by SILGen, IRGen and the runtime. Instead, previous
commits already ensure that SILGen determines the set of conformances to be
emitted, triggering conformance checking as needed.
Currently Sema completes all _ObjectiveCBridgeable conformances it thinks
are needed in SILGen and runtime dynamic casts, but that's about to change.
When emitting conformances for an imported type we would skip incomplete
conformances. Now that we have a long-lived type checker instance, there
is no longer any reason to do that. Looking up witnesses from an
incomplete conformance will trigger conformance checking as needed.
Furthermore, conformances emitted in this path are emitted lazily, so if
a conformance is not used, no conformance checking will take place.
A change in behavior only occurs after subsequent changes to remove Sema's
eager checking of ClangImporter-synthesized _ObjectiveCBridgeable
conformances; at that point, we must be prepared to lazily emit these
incomplete conformances.
- Don't forget to walk the top-level 'main' function
- Force _ObjectiveCBridgeable and _BridgedStoredNSError conformances
for types mentioned in apply instructions, existential erasure and
casts
- Only walk each unique CanType once, and skip non-ClangImporter
synthesized conformances completely
- Add a few missing cases
SILGen has the ability to lazily emit ClangImporter-synthesized
conformances. Sema builds a per-SourceFile list of "used" conformances,
which are forced to be emitted by SILGen. All other conformances can be
emitted lazily.
Some of these "used" conformances are in fact not referenced by SILGen
at all, but must exist for emission by IRGen so that they can be
referenced from type metadata accessors, as well as available at
runtime for the dynamic cast machinery.
To handle these cases, add an AST walk to SILGen which emits the types
of stored properties, the superclass of a class, and a few other
things that might not be referenced directly from SIL.
For now, this is all redundant because Sema forces the right
conformances anyway, but that's going to change soon.
This allows the conversion of the Windows `BOOL` type to be converted to
`Bool` implicitly. The implicit bridging allows for a more ergonomic
use of the native Windows APIs in Swift.
Due to the ambiguity between the Objective C `BOOL` and the Windows
`BOOL`, we must manually map the `BOOL` type to the appropriate type.
This required lifting the mapping entry for `ObjCBool` from the mapped
types XMACRO definition into the inline definition in the importer.
Take the opportunity to simplify the mapping code.
Adjust the standard library usage of the `BOOL` type which is now
eclipsed by the new `WindowsBool` type, preferring to use `Bool`
whenever possible.
Thanks to Jordan Rose for the suggestion to do this and a couple of
hints along the way.
The initialization of an instance property that has an attached
property delegate involves the initial value written on the property
declaration, the implicit memberwise initializer, and the default
arguments to the implicit memberwise initializer. Implement SILGen
support for each of these cases.
There is a small semantic change to the creation of the implicit
memberwise initializer due to SE-0242 (default arguments for the
memberwise initializer). Specifically, the memberwise initializer will
use the original property type for the parameter to memberwise
initializer when either of the following is true:
- The corresponding property has an initial value specified with the
`=` syntax, e.g., `@Lazy var i = 17`, or
- The corresponding property has no initial value, but the property
delegate type has an `init(initialValue:)`.
The specific case that changed is when a property has an initial value
specified as a direct initialization of the delegate *and* the
property delegate type has an `init(initialValue:)`, e.g.,
```swift
struct X {
@Lazy(closure: { ... })
var i: Int
}
```
Previously, this would have synthesized an initializer:
```swift
init(i: Int = ???) { ... }
```
However, there is no way for the initialization specified within the
declaration of i to be expressed via the default argument. Now, it
synthesizes an initializer:
```swift
init(i: Lazy<Int> = Lazy(closure: { ... }))
```
The initializer associated with a lazy property should not be executed
directly, because it is subsumed by code synthesized into the
getter. Generalize the terminology here so we can re-use this path for
property delegate initialization.
Tear out the hacks to pre-substitute opaque types before they enter the SIL type system.
Implement UnderlyingToOpaqueExpr as bitcasting the result of the underlying expression from the
underlying type to the opaque type.
To represent the abstracted interface of an opaque type, we need a generic signature that refines
the outer context generic signature with an additional generic parameter representing the underlying
type and its exposed constraints. Opaque types also need to be keyed by their originating decl, so
that we can treat values of the same opaque type as the same. When we check a FuncDecl with an
opaque type specified as its return type, create an OpaqueTypeDecl and associate it with the
originating decl. (A representation for *types* derived from the opaque decl will come next.)
In a few corner cases we built DeclRefExpr and MemberRefExpr
for references to types. These should just be TypeExpr so that
SILGen doesn't have to deal with it.
This also fixes a bug where a protocol typealias with an
unbound generic type could not be accessed properly from
expression context, but that is just so incredibly obscure.