Introduce abstraction patterns for curried C-functions-as-methods for type lowering, and plumb the "foreign self parameter index" through call emission so that we emit the "self" parameter in the right position. This gets us handling C functions imported as methods with explicit swift_name attributes in simple, fully-applied cases. There's still more work to be done for properties, partial applications, and initializers introduced by extensions.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
When a dependent type is mapped into context, the result will either be
an archetype or a concrete type. The latter occurs if a same-type
constraint exists between the dependent type and the concrete type.
The logic to decide if a type should be passed directly or indirectly
was not handling this case if an interface type was passed down -- we
would just check if there was a class constraint present.
This resulted in mismatching conventions between an interface type and
its corresponding contextual type, which would trigger assertions.
Note that same-type constraints between generic parameters and concrete
types are still not supported for other reasons; the subject of the
constraint must still be an associated type of a generic parameter.
Fixes <rdar://problem/24687460>.
If an abstraction pattern has interface types in it, we
already enforce that it was constructed with a generic
signature.
This generic signature is only used to answer questions
about the abstraction pattern's own formal type, and
not with the substituted type.
So only put type lowering cache entries in the dependent
cache if they contain interface types in the substituted
type. Otherwise, if only the abstraction pattern has
interface types in it, the entry can live in the
independent cache, allowing it to be looked up without
a pushGenericContext() / popGenericContext() call.
For correctness, we now have to store the generic signature
in the type key as well. Subsequent changes should reduce
the size of the cache, by lowering fewer archetypes.
NFC, since nothing uses this for now.
When lowering the original unsubstituted type to check for parameters
and results being passed indirectly, be careful to map it to archetypes,
since the abstraction pattern's generic signature might not equal
M.Types.getCurGenericContext().
Also, don't use '==' to compare canonical interface types.
NFC for now, since this code is largely not exercised.
- isTypeParameter() -- check if this is an archetype or dependent
interface type.
- requiresClass() -- check if this is a class-constrained type
parameter.
The old isOpaque() check has been replaced by
(isTypeParameter() && !requiresClass(moduleDecl)).
This allows us to pass the ModuleDecl on down to
GenericSignature::requiresClass(), enabling the use of
interface types in abstraction patterns.
NFC for now.
Instead of bodging a representation of the SIL capture parameters for a closure into the formal type of closure SILDeclRefs, introduce those parameters in a separate lowering step. This lets us clean up some TypeLowering code that was tolerating things like SILBoxTypes and naked LValueTypes in formal types for nefarious ends (though requires some hacks in SILGen to keep the representation of curry levels consistent, which is something I hope to clean up next). This also decouples the handling of captures from the handling of other parameters, which should enable us to make them +0. For now, there should be NFC.
Probably SILGenPoly.cpp should be named SILGenThunk.cpp, but I'm saving
that for if I ever extract the duplication between bridging thunks and
re-abstraction thunks.
The isDependentType() query is woefully misunderstood. Some places
seem to want it to mean "a generic type parameter of dependent member
type", which corresponds to what is effectively a type parameter in
the language, while others want it to mean "contains a type parameter
anywhere in the type". Tease out these two meanings in
isTypeParameter() and hasTypeParameter(), respectively, and sort out
the callers.
Swift SVN r29945
SILFunctionType of the method instead of its formal type.
Gives more accurate information to the @encoding, makes
foreign error conventions work implicitly, and allows
IRGen's Swift-to-Clang to avoid duplicating arbitrary
amounts of the bridging logic from SILGen.
Some finagling was required in order to avoid calling
getConstantFunctionType from within other kinds of
lowering, which might have re-entered a generic context.
Also required fixing a bug with the type lowering of
optional DynamicSelfTypes where we would end up with
a substituted type in the lowered type.
Also, for some reason, our @encoding for -dealloc
methods was pretending that there was a formal parameter.
There didn't seem to be any justification for this,
and it's not like Clang does that. Fixed.
This commit reapplies r29266 with a conservative build fix
that disables ObjC property descriptors for @objc properties
that lack a getter. That should only be possible in SIL
files, because @objc should force accessors to be synthesized.
Arguably, Sema shouldn't be marking things implicitly @objc
in SIL files, but I'll leave that decision open for now.
Swift SVN r29272
SILFunctionType of the method instead of its formal type.
Gives more accurate information to the @encoding, makes
foreign error conventions work implicitly, and allows
IRGen's Swift-to-Clang to avoid duplicating arbitrary
amounts of the bridging logic from SILGen.
Some finagling was required in order to avoid calling
getConstantFunctionType from within other kinds of
lowering, which might have re-entered a generic context.
Also required fixing a bug with the type lowering of
optional DynamicSelfTypes where we would end up with
a substituted type in the lowered type.
Also, for some reason, our @encoding for -dealloc
methods was pretending that there was a formal parameter.
There didn't seem to be any justification for this,
and it's not like Clang does that. Fixed.
Swift SVN r29266
preserve the original method name.
This heuristic is based on the Objective-C selector and therefore
doesn't really handle factory methods that would conflict with
initializers, but we can hope that those simply don't come up in
the wild.
It's not clear that this is the best thing to do --- it tends to
promote the non-throwing API over what's probably a newer, throwing
API --- but it's significantly easier, and it unblocks code without
creating deployment problems.
Swift SVN r28066
results when finding bridged types, rather than reinventing
(well, pre-inventing) the same thing elsewhere.
Doing this apparently forces AbstractionPattern to deal
with ObjC protocol methods for the first time, which are
generic and therefore require even the Clang-based
abstraction patterns to propagate generic signatures.
Use this infrastructure to allow foreign error conventions
to suppress the wrapping of nonnull bridged collection results
in a level of optionality. We can't treat nil results as
an empty collection while simultaneously treating them as
an error signal.
Swift SVN r28022
We still don't actually handle these correctly, but at least
we have sensible information for them now.
Also, remember that we're working with canonical generic
signatures in more places.
Swift SVN r27388
This is necessary for correctly dealing with non-standard
ownership conventions in secondary positions, and it should
also help with non-injective type imports (like BOOL/_Bool).
But right now we aren't doing much with it.
Swift SVN r26954
To do this with complete accuracy requires mapping the dependent types into a context, but isOpaque is currently only used as a sanity check in assertions, and a tuple being matched to a class-constrained archetype is an unlikely enough occurrence that it's probably OK to accept this inaccuracy instead of trying to push generic contexts all the way down into isOpaque's clients.
Swift SVN r11824
with qualifiers on it, we have two distinct types:
- LValueType(T) aka @lvalue T, which is used for mutable values on the LHS of an
assignment in the typechecker.
- InOutType(T) aka @inout T, which is used for @inout arguments, and the implicit
@inout self argument of mutable methods on value types. This type is also used
at the SIL level for address types.
While I detangled a number of cases that were checking for LValueType (without checking
qualifiers) and only meant @inout or @lvalue, there is more to be done here. Notably,
getRValueType() still strips @inout, which is totally and unbearably wrong.
Swift SVN r11727