In 1ae317dd88, all the machinery was added
to enable calling ObjC functions that have both async and error
conventions. The handling that was added for matching up arguments and
parameters, however, failed to handle functions that had both foreign
async and foreign error and other arguments. Here, that handling is
fixed.
The fix is in four parts:
- Reverting to a single call to CallSite::emit to emit the formal
params. At this point, the foreign async and/or error params will be
claimed as well.
- Separately counting the async and error parameters in
ParamLowering::claimParams to ensure we get the right parameter
slices.
- Letting ArgEmitter::maybeEmitForeignArgument look for an error
parameter even if it already found an async parameter.
- Letting ArgEmitter::maybeEmitForeignArgument keep looking for foreign
arguments after it finds one.
rdar://80704984
The validation-test suite was incorrectly being run without the
concurrency feature enabled, so the tests were disabled. Now that
they're running, they need fixed availability annotations.
This enabled a gross idiom that should not have been allowed in the first place:
typealias G<T> = Any where T : P
protocol P {}
protocol Q : G<Self> {} // Q inherits from P now!
I'd like to ban this, assuming nothing is actually relying on this behavior.
Returning a null GenericSignature is not the right way to break a cycle,
because then callers have to be careful to handle the case of a null
GenericSignature together with a non-null GenericParamList, for example
in applyGenericArguments().
An even worse problem can occur when a GenericSignatureRequest for a
nested generic declaration requests the signature of the parent context,
which hits a cycle. In this case, we would build a signature where
the first generic parameter did not have depth 0.
This makes the requirement machine upset, so this patch implements a new
strategy to break such cycles. Instead of returning a null
GenericSignature, we build a signature with the correct generic
parameters, but no requirements. The generic parameters can be computed
just by traversing GenericParamLists, which does not trigger more
GenericSignatureRequests, so this should be safe.
When converting an ObjC method type which is being called as async to a
Swift function type, some of the values passed to the ObjC method's
completion handler are converted to return values of the Swift function.
The flag and error parameters, however, if present, are ignored.
When abstracting the result type for the Swift method, the formal type
of the corresponding parameter in the ObjC method's completion handler
is used. Digging out that parameter entails indexing into the
parameters of the completion handler. Previously, the indexing logic
relied on the error appearing before the flag if both appeared before
the value of interest. Here, the indexing is tweaked to check both
special indices for each possible index until the first that matches
neither is found.
rdar://81625544
In the synthesized completion handler that is passed to ObjC methods
that are called as async, the formal type of each argument is the
corresponding parameter of the formal type of the block. The non-error,
non-index arguments need to be prepared so that they can be used to
fulfill the continuation; the lambda which does that preparation for
each such argument takes the formal type of that argument. As such, the
call to that lambda needs to pass the type of the corresponding
parameter of the formal type of the block to that lambda. Doing so
entails skipping over the error and flag parameters if they appear
before some of the non-error, non-index arguments.
Previously, no parameters were skipped over. Consequently, when an
error or flag argument preceded one of the non-error, non-index
arguments, the wrong formal type was passed to the preparation lambda.
Here, that is fixed by passing the correct index. The to-be-used
indices for the formal block parameters are the same as the to-be-used
indices for the lowered block parameters minus one reflecting the fact
that the lowered block always has an initial block_storage parameter as
the first argument which the formal type never has.
rdar://81617749
Previously, the function emitCBridgedToNativeValue handled three
situations around optionals:
- Bridged?, Native?
- Bridged, Native?
- Bridged, Native
Here, handling for the fourth case
- Bridged?, Native
is added.
To enable this, the number of Optional wrappings that the bridged type
has that the native type does not is passed in to the function. Then,
in the portions of the function where actual transformations are done,
the values are unwrapped an appropriate number of times. Mostly that
means force unwrapping N times before doing the transformation. In the
case of types that conform to _ObjectiveCBridgeable, however, it means
force unwrapping the value N-1 times after doing the transformation
because _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC
performs one layer of unwrapping itself.
rdar://81590807
Previously, SILGen assumed that a foreign function could either have a
foreign async convention or a foreign error convention, but if it had
both, the error would be subsumed into the completion. That resulted in
failures to emit code for async calls of functions like
```
- (BOOL)minimalWithError:(NSError* _Nullable*)error
completionHandler:(void (^ _Nonnull)(void))completionHandler;
```
Here, SILGen gains the ability to emit such functions. To enable that,
a few changes were required when both conventions are present:
- a separate argument for each convention is used
- the ResultPlan is a ForeignErrorResultPlan nesting a
ForeignAsyncResultPlan
- the continuation is always of the form UnsafeContinuation<_, Error>
regardless of whether the completion handler takes an error
- the foreign error block fills the continuation with the error that was
passed by reference out of the ObjC method call
- the foreign error block branches to the block containing the await
instruction
rdar://80704984
Stopped validation-test/compiler_crashers_2_fixed/rdar79383990.swift
from trying to call -[NSBackgroundActivityScheduler scheduleWithBlock:]
async--that method is now annotated NS_SWIFT_DISABLE_ASYNC.
Previously, AbstractionPattern::getOpaque() was used for async
continuations. That was problematic for functions like
```objc
- (void)performVoid2VoidWithCompletion:(void (^ _Nonnull)(void (^ _Nonnull)(void)))completion;
```
whose completion takes a closure. Doing so resulted in attempting to
build a block to func thunk where one of the functions had an out
parameter.
Instead, use the AbstractionPattern(ty).
rdar://79383990
The solver's simplifyType() can produce a DependentMemberType with a
concrete or archetype base, if that associated type could not be
resolved during associated type inference.
mapTypeOutOfContext() could assert when given a type that violates
invariants in this manner. Instead, let's directly call subst() here,
providing a conformance lookup function (which will probably end up
returning ErrorTypes).
Fixes https://bugs.swift.org/browse/SR-14672 / rdar://problem/78626943.
Let's make use of a newly added "disable for performance" flag to
allow solver to consider overload choices where the only issue is
missing one or more labels - this makes it for a much better
diagnostic experience without any performance impact for valid code.
`PreCheckExpression` already skips calls, make sure that invalid subscripts,
dynamic subscript, ObjC literals preserve paren/tuple for an index/argument.
Resolves: rdar://61749633
While ModuleDecl::lookupConformance() did the right thing here, we have
another entry point, TypeChecker::containsProtocol(), that also needs
to special-case Error.
Fixes https://bugs.swift.org/browse/SR-13734 / rdar://problem/70338670.
AbstractionPattern::matchesTuple() is used by various assertions, and
the condition was too strict. Relax the condition to fix an assertion
failure in the case where an opaque result type has a tuple as its
underlying type.
Fixes https://bugs.swift.org/browse/SR-14426 / rdar://problem/76057095.
We fail to resolve the extended type if an extension is not declared at the top level. This causes us to diagnose a lookup failure on `Self`. If the extended type is a protocol, we thus end up with a nominal Self type that’s not a class, violating the assertion that’s currently in place. To fix the crasher, convert the assertion to an `if` condition and issue a generic "cannot find type 'Self' in scope" in the else case.
Fixes rdar://76329083
A protocol can constrain an associated type to Self:
protocol P {
associatedtype A : Q where A.B == Self
}
protocol Q {
associatedtype B
}
And a class might conform to this protocol:
class C : P {
typealias A = D
}
class D : Q {
typealias B = C
}
The generic signature <Self where Self : P, Self : C> is built during
conformance checking. Since Self : C, we must have that Self.A == D;
since D.B == C, the requierement 'A.B == Self' in protocol P implies
that 'Self == C'. So the correct minimized signature here is
<Self where Self == C>.
This wasn't handled properly before, because of assumptions in
removeSelfDerived() and a couple of other places.
Fixes rdar://71677712, rdar://76155506, https://bugs.swift.org/browse/SR-10033,
https://bugs.swift.org/browse/SR-13884.
When an extension is nested inside of an invalid decl context, it is
going to pull the signature of its nearest enclosing context instead of
its extended type. This leads to a null signature since the nearest
enclosing context for an extension should always be its parent source
file.
rdar://76049852
IsBindableVisitor is part of TypeBase::substituteBindingsTo(), which
is used for two things:
- Checking if one contextual type is a proper substitution of another
contextual type, used in the solver
- To compute the substituted generic signature when lowering a SIL
function type
In the first case, we're interested in knowing if the substitution
succeeds or fails. In the second case, we know the substitution is
correct by construction, and we're trying to recover the generic
requirements.
In the second case though, the substituted type might be an
interface type, and if the interface type is constrained to a
concrete type in the original type's generic signature, we would
conclude that the substitution should fail.
This is incorrect, and we should just skip the check if the
substituted type is an interface type -- we do not have enough
information to know if it succeeds, and instead we must assume it
does because otherwise the substituted type passed in to type
lowering must be incorrect.
Fixes https://bugs.swift.org/browse/SR-13849.
We rebuild a signature after dropping redundant conformance requirements,
since conformance requirements change the canonical type and conformance
access path computation.
When doing this, instead of using the canonical requirements from the
signature, use the original as-written requirements.
This fixes some weirdness around concrete same-type requirements.
There's a philosophical benefit here too -- since we rebuild the
signature without ever having built the old signature, we never create
an invalid GenericSignature in the ASTContext.
Fixes rdar://problem/75690903.
When requestifying the synthesis of the main function for the type
annotated @main via SynthesizeMainFunctionRequest, what were previously
were bailouts from AttributeChecker::visitMainTypeAttr had to become
returns of nullptr from SynthesizeMainFunctionRequest::evaluate.
Consequently, AttributeChecker::visitMainTypeAttr must check whether
synthesis actually succeeded before proceeding to to register the main
decl for a file.
In simple cases, this happened to work because
SourceFile::registerMainDecl would return early if the decl being
registered was the same as the already registered main decl and in
particular if the decl being registered was nullptr and the previously
registered one was nullptr as well. When, however, there are multiple
types annotated @main, if a function is successfully synthesized for one
type but synthesis fails for the second, an attempt will be made to
register nullptr as the main decl and will move past the check at the
beginning of SourceFile::registerMainDecl, resulting in a crash.
Here, we bail from AttributeChecker::visitMainTypeAttr if function
synthesis fails and add an assert to SourceFile::registerMainDecl that
the provided decl is non-null.
rdar://75547146