ProtocolConformanceRef already has an invalid state. Drop all of the
uses of Optional<ProtocolConformanceRef> and just use
ProtocolConformanceRef::forInvalid() to represent it. Mechanically
translate all of the callers and callsites to use this new
representation.
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711
This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:
- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
of the function to its concrete implementation. This will allow, for instance, a protocol
witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
to the protocol interface without relying on the pile of hacks that is the `witness_method`
protocol.
- A bool for whether the generic signature of the function is "implied" by the substitutions.
If true, the generic signature isn't really part of the calling convention of the function.
This will allow closure types to distinguish a closure being passed to a generic function, like
`<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
which will make it easier for us to differentiate the representation of those as types, for
instance by giving them different pointer authentication discriminators to harden arm64e
code.
This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.
This does bifurcate some existing APIs:
- SILFunctionType now has two accessors to get its generic signature.
`getSubstGenericSignature` gets the generic signature that is used to apply its
substitution map, if any. `getInvocationGenericSignature` gets the generic signature
used to invoke the function at apply sites. These differ if the generic signature is
implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
and results of the function. They now have two APIs to get that type. `getInterfaceType`
returns the unsubstituted type of the generic interface, and
`getArgumentType`/`getReturnValueType` produce the substituted type that is used at
apply sites.
Switch most callers to explicit indices. The exceptions lie in things that needs to manipulate the parsed output directly including the Parser and components of the ASTScope. These are included as friend class exceptions.
Due to insufficiently robust argument emission code, certain combinations of language features could cause a call to a property wrapper backing initalizer to have mismatched argument types, causing an assertion failure in SILGenApply. This commit moves SILGenFunction::emitApplyOfPropertyWrapperBackingInitializer() into SILGenApply so it can use CallEmission and PreparedArguments to emit the call with full generality. Fixes rdar://problem/55995892.
Structurally prevent a number of common anti-patterns involving generic
signatures by separating the interface into GenericSignature and the
implementation into GenericSignatureBase. In particular, this allows
the comparison operators to be deleted which forces callers to
canonicalize the signature or ask to compare pointers explicitly.
Teach SILGen to emit a separate SIL function to capture the
initialization of the backing storage type for a wrapped property
based on the wrapped value. This eliminates manual code expansion at
every use site.
Unfortuantely this commit is bigger than I would like but I couldn't think
of any reasonable ways to split it up.
The general idea here is that capture computation is now done for a
SILDeclRef and not an AnyFunctionRef. This allows SIL to represent the
captures of a default argument generator.
The only place this was used in Decl.h was the failability kind of a
constructor.
I decided to replace this with a boolean isFailable() bit. Now that
we have isImplicitlyUnwrappedOptional(), it seems to make more sense
to not have ConstructorDecl represent redundant information which
might not be internally consistent.
Most callers of getFailability() actually only care if the result is
failable or not; the few callers that care about it being IUO can
check isImplicitlyUnwrappedOptional() as well.
Since the return value of getAccessor() depends on mutable state, it
does not make sense in the request evaluator world. Let's begin by
removing some utility methods derived from getAccessor(), replacing
calls to them with calls to getAccessor().
This improves on the previous situation:
- The request ensures that the backing storage for lazy properties
and property wrappers gets synthesized first; previously it was
only somewhat guaranteed by callers.
- Instead of returning a range this just returns an ArrayRef,
which simplifies clients.
- Indexing into the ArrayRef is O(1), which addresses some FIXMEs
in the SIL optimizer.
This removes a bit of global state from the TypeChecker class, and
allows C function pointers to be formed to closures that capture
local functions, but have no transitive captures.
We identify overrides using the same key path descriptor as the base, but an overridden base
may not have a property descriptor if it's @objc or fragile. Fixes rdar://problem/51479334.
Windows has a special symbol `__ImageBase` whcih provides the constant
value of the base of the image. This is roughly equivalent to the
`__dso_handle` on the ELF and MachO targets. Use this to construct the
value for the `#dsohandle` rather than attempting to use the
non-existent symbol `__dso_handle`. This fixes the
dsohandle-multi-module validation test on Windows.
Add `llvm_unreachable` to mark covered switches which MSVC does not
analyze correctly and believes that there exists a path through the
function without a return value.
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.
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.
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.
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.