Skip to content

[Test] Added for call-as-async Optional<NS_EXTENSIBLE_STRING_ENUM>. #38786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 50 additions & 35 deletions lib/SILGen/SILGenBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,16 +1020,11 @@ SILGenFunction::emitBlockToFunc(SILLocation loc,
loc, thunkedFn, SILType::getPrimitiveObjectType(loweredFuncTy));
}

static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
SILLocation loc,
ManagedValue v,
CanType bridgedType,
CanType nativeType,
SILType loweredNativeTy,
bool isCallResult,
SGFContext C) {
static ManagedValue emitCBridgedToNativeValue(
SILGenFunction &SGF, SILLocation loc, ManagedValue v, CanType bridgedType,
SILType loweredBridgedTy, CanType nativeType, SILType loweredNativeTy,
int bridgedOptionalsToUnwrap, bool isCallResult, SGFContext C) {
assert(loweredNativeTy.isObject());
SILType loweredBridgedTy = v.getType();
if (loweredNativeTy == loweredBridgedTy.getObjectType())
return v;

Expand All @@ -1040,37 +1035,50 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
if (!bridgedObjectType) {
auto helper = [&](SILGenFunction &SGF, SILLocation loc, SGFContext C) {
auto loweredNativeObjectTy = loweredNativeTy.getOptionalObjectType();
return emitCBridgedToNativeValue(SGF, loc, v, bridgedType,
nativeObjectType,
loweredNativeObjectTy,
isCallResult, C);
return emitCBridgedToNativeValue(
SGF, loc, v, bridgedType, loweredBridgedTy, nativeObjectType,
loweredNativeObjectTy, bridgedOptionalsToUnwrap, isCallResult, C);
};
return SGF.emitOptionalSome(loc, loweredNativeTy, helper, C);
}

// Optional-to-optional.
auto helper =
[=](SILGenFunction &SGF, SILLocation loc, ManagedValue v,
SILType loweredNativeObjectTy, SGFContext C) {
return emitCBridgedToNativeValue(SGF, loc, v, bridgedObjectType,
nativeObjectType, loweredNativeObjectTy,
isCallResult, C);
auto helper = [=](SILGenFunction &SGF, SILLocation loc, ManagedValue v,
SILType loweredNativeObjectTy, SGFContext C) {
return emitCBridgedToNativeValue(
SGF, loc, v, bridgedObjectType,
loweredBridgedTy.getOptionalObjectType(), nativeObjectType,
loweredNativeObjectTy, bridgedOptionalsToUnwrap, isCallResult, C);
};
return SGF.emitOptionalToOptional(loc, v, loweredNativeTy, helper, C);
}
if (auto bridgedObjectType = bridgedType.getOptionalObjectType()) {
return emitCBridgedToNativeValue(
SGF, loc, v, bridgedObjectType,
loweredBridgedTy.getOptionalObjectType(), nativeType, loweredNativeTy,
bridgedOptionalsToUnwrap + 1, isCallResult, C);
}

auto unwrapBridgedOptionals = [&](ManagedValue v) {
for (int i = 0; i < bridgedOptionalsToUnwrap; ++i) {
v = SGF.emitPreconditionOptionalHasValue(loc, v,
/*implicit*/ true);
};
return v;
};

// Bridge ObjCBool, DarwinBoolean, WindowsBool to Bool when requested.
if (nativeType == SGF.SGM.Types.getBoolType()) {
if (bridgedType == SGF.SGM.Types.getObjCBoolType()) {
return emitBridgeForeignBoolToBool(SGF, loc, v,
return emitBridgeForeignBoolToBool(SGF, loc, unwrapBridgedOptionals(v),
SGF.SGM.getObjCBoolToBoolFn());
}
if (bridgedType == SGF.SGM.Types.getDarwinBooleanType()) {
return emitBridgeForeignBoolToBool(SGF, loc, v,
return emitBridgeForeignBoolToBool(SGF, loc, unwrapBridgedOptionals(v),
SGF.SGM.getDarwinBooleanToBoolFn());
}
if (bridgedType == SGF.SGM.Types.getWindowsBoolType()) {
return emitBridgeForeignBoolToBool(SGF, loc, v,
return emitBridgeForeignBoolToBool(SGF, loc, unwrapBridgedOptionals(v),
SGF.SGM.getWindowsBoolToBoolFn());
}
}
Expand All @@ -1080,8 +1088,8 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
auto bridgedMetaTy = cast<AnyMetatypeType>(bridgedType);
if (bridgedMetaTy->hasRepresentation() &&
bridgedMetaTy->getRepresentation() == MetatypeRepresentation::ObjC) {
SILValue native =
SGF.B.emitObjCToThickMetatype(loc, v.getValue(), loweredNativeTy);
SILValue native = SGF.B.emitObjCToThickMetatype(
loc, unwrapBridgedOptionals(v).getValue(), loweredNativeTy);
// *NOTE*: ObjCMetatypes are trivial types. They only gain ARC semantics
// when they are converted to an object via objc_metatype_to_object.
assert(!v.hasCleanup() && "Metatypes are trivial and should not have "
Expand All @@ -1097,7 +1105,8 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
== AnyFunctionType::Representation::Block
&& nativeFTy->getRepresentation()
!= AnyFunctionType::Representation::Block) {
return SGF.emitBlockToFunc(loc, v, bridgedFTy, nativeFTy,
return SGF.emitBlockToFunc(loc, unwrapBridgedOptionals(v), bridgedFTy,
nativeFTy,
loweredNativeTy.castTo<SILFunctionType>());
}
}
Expand All @@ -1106,8 +1115,10 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
if (auto conformance =
SGF.SGM.getConformanceToObjectiveCBridgeable(loc, nativeType)) {
if (auto result = emitBridgeObjectiveCToNative(SGF, loc, v, bridgedType,
conformance))
return *result;
conformance)) {
--bridgedOptionalsToUnwrap;
return unwrapBridgedOptionals(*result);
}

assert(SGF.SGM.getASTContext().Diags.hadAnyError() &&
"Bridging code should have complained");
Expand All @@ -1118,7 +1129,8 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
if (nativeType->isAny()) {
// If this is not a call result, use the normal erasure logic.
if (!isCallResult) {
return SGF.emitTransformedValue(loc, v, bridgedType, nativeType, C);
return SGF.emitTransformedValue(loc, unwrapBridgedOptionals(v),
bridgedType, nativeType, C);
}

// Otherwise, we use more complicated logic that handles results that
Expand All @@ -1130,7 +1142,8 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
CanType anyObjectTy =
SGF.getASTContext().getAnyObjectType()->getCanonicalType();
if (bridgedType != anyObjectTy) {
v = SGF.emitTransformedValue(loc, v, bridgedType, anyObjectTy);
v = SGF.emitTransformedValue(loc, unwrapBridgedOptionals(v), bridgedType,
anyObjectTy);
}

// TODO: Ever need to handle +0 values here?
Expand All @@ -1143,8 +1156,8 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
// Bitcast to Optional. This provides a barrier to the optimizer to prevent
// it from attempting to eliminate null checks.
auto optionalBridgedTy = SILType::getOptionalType(loweredBridgedTy);
auto optionalMV =
SGF.B.createUncheckedBitCast(loc, v, optionalBridgedTy);
auto optionalMV = SGF.B.createUncheckedBitCast(
loc, unwrapBridgedOptionals(v), optionalBridgedTy);
return SGF.emitApplyOfLibraryIntrinsic(loc,
SGF.getASTContext().getBridgeAnyObjectToAny(),
SubstitutionMap(), optionalMV, C)
Expand All @@ -1153,9 +1166,9 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,

// Bridge NSError to Error.
if (bridgedType == SGF.SGM.Types.getNSErrorType())
return SGF.emitBridgedToNativeError(loc, v);
return SGF.emitBridgedToNativeError(loc, unwrapBridgedOptionals(v));

return v;
return unwrapBridgedOptionals(v);
}

ManagedValue SILGenFunction::emitBridgedToNativeValue(SILLocation loc,
Expand All @@ -1166,8 +1179,10 @@ ManagedValue SILGenFunction::emitBridgedToNativeValue(SILLocation loc,
SGFContext C,
bool isCallResult) {
loweredNativeTy = loweredNativeTy.getObjectType();
return emitCBridgedToNativeValue(*this, loc, v, bridgedType, nativeType,
loweredNativeTy, isCallResult, C);
SILType loweredBridgedTy = v.getType();
return emitCBridgedToNativeValue(
*this, loc, v, bridgedType, loweredBridgedTy, nativeType, loweredNativeTy,
/*bridgedOptionalsToUnwrap=*/0, isCallResult, C);
}

/// Bridge a possibly-optional foreign error type to Error.
Expand Down
9 changes: 9 additions & 0 deletions test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#define MAIN_ACTOR __attribute__((__swift_attr__("@MainActor")))
#define MAIN_ACTOR_UNSAFE __attribute__((__swift_attr__("@_unsafeMainActor")))

#define NS_EXTENSIBLE_STRING_ENUM __attribute__((swift_wrapper(struct)));
typedef NSString *Flavor NS_EXTENSIBLE_STRING_ENUM;

@protocol ServiceProvider
@property(readonly) NSArray<NSString *> *allOperations;
-(void)allOperationsWithCompletionHandler:(void (^)(NSArray<NSString *> *))completion;
Expand Down Expand Up @@ -84,6 +87,12 @@ typedef void (^CompletionHandler)(NSString * _Nullable, NSString * _Nullable_res
-(void)asyncImportSame:(NSString *)operation replyTo:(void (^)(NSInteger))handler __attribute__((swift_async(none)));

-(void)overridableButRunsOnMainThreadWithCompletionHandler:(MAIN_ACTOR_UNSAFE void (^ _Nullable)(NSString *))completion;
- (void)obtainClosureWithCompletionHandler:(void (^)(void (^_Nullable)(void),
NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
- (void)getIceCreamFlavorWithCompletionHandler:
(void (^)(Flavor flavor, NSError *__nullable error))completionHandler;
@end

@protocol RefrigeratorDelegate<NSObject>
Expand Down
4 changes: 4 additions & 0 deletions test/SILGen/objc_async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ func testSlowServer(slowServer: SlowServer) async throws {
let _: ((Any) -> Void, (Any) -> Void) = await slowServer.performId2VoidId2Void()

let _: String = try await slowServer.findAnswerFailingly()

let _: () -> Void = try await slowServer.obtainClosure()

let _: Flavor = try await slowServer.iceCreamFlavor()
}

func testGeneric<T: AnyObject>(x: GenericObject<T>) async throws {
Expand Down
25 changes: 25 additions & 0 deletions validation-test/compiler_crashers_2_fixed/Inputs/rdar80704382.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <Foundation/Foundation.h>

#pragma clang assume_nonnull begin

typedef NSString *FileProviderItemIdentifier NS_EXTENSIBLE_STRING_ENUM;
FileProviderItemIdentifier const
FileProviderRootContainerItemIdentifier NS_SWIFT_NAME(FileProviderItemIdentifier.rootContainer);
FileProviderItemIdentifier const
FileProviderWorkingSetContainerItemIdentifier NS_SWIFT_NAME(FileProviderItemIdentifier.workingSet);
FileProviderItemIdentifier const
FileProviderTrashContainerItemIdentifier NS_SWIFT_NAME(FileProviderItemIdentifier.trashContainer);
typedef NSString *FileProviderDomainIdentifier NS_EXTENSIBLE_STRING_ENUM;

@interface PFXObject : NSObject
+ (void)getIdentifierForUserVisibleFileAtURL:(NSURL *)url
completionHandler:
(void (^)(FileProviderItemIdentifier __nullable
itemIdentifier,
FileProviderDomainIdentifier __nullable
domainIdentifier,
NSError *__nullable error))
completionHandler;
@end

#pragma clang assume_nonnull end
23 changes: 23 additions & 0 deletions validation-test/compiler_crashers_2_fixed/Inputs/rdar80704382.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "rdar80704382.h"

#pragma clang assume_nonnull begin

@implementation PFXObject
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
+ (void)getIdentifierForUserVisibleFileAtURL:(NSURL *)url
completionHandler:
(void (^)(FileProviderItemIdentifier __nullable
itemIdentifier,
FileProviderDomainIdentifier __nullable
domainIdentifier,
NSError *__nullable error))
completionHandler {
completionHandler(@"item_id", @"file_id", NULL);
}
@end

#pragma clang assume_nonnull end
29 changes: 29 additions & 0 deletions validation-test/compiler_crashers_2_fixed/Inputs/rdar81590807.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <Foundation/Foundation.h>

#pragma clang assume_nonnull begin

@interface PFXObject : NSObject {
}
- (void)continuePassSyncWithCompletionHandler:(void (^)(void (^_Nullable)(void),
NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
- (void)continuePassAsyncWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
- (void)continueFailSyncWithCompletionHandler:(void (^)(void (^_Nullable)(void),
NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
- (void)continueFailAsyncWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
- (void)continueIncorrectWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3)));
@end

#pragma clang assume_nonnull end
54 changes: 54 additions & 0 deletions validation-test/compiler_crashers_2_fixed/Inputs/rdar81590807.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "rdar81590807.h"

#pragma clang assume_nonnull begin

@implementation PFXObject
- (void)continuePassSyncWithCompletionHandler:(void (^)(void (^_Nullable)(void),
NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3))) {
completionHandler(
^{
NSLog(@"passSync");
},
NULL, YES);
}
- (void)continuePassAsyncWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3))) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
completionHandler(
^{
NSLog(@"passAsync");
},
NULL, YES);
});
}
- (void)continueFailSyncWithCompletionHandler:(void (^)(void (^_Nullable)(void),
NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3))) {
completionHandler(
NULL, [NSError errorWithDomain:@"failSync" code:1 userInfo:nil], NO);
}
- (void)continueFailAsyncWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3))) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
completionHandler(
NULL, [NSError errorWithDomain:@"failAsync" code:2 userInfo:nil], NO);
});
}
- (void)continueIncorrectWithCompletionHandler:
(void (^)(void (^_Nullable)(void), NSError *_Nullable,
BOOL))completionHandler
__attribute__((swift_async_error(zero_argument, 3))) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
completionHandler(NULL, NULL, NO);
});
}
@end

#pragma clang assume_nonnull end
24 changes: 24 additions & 0 deletions validation-test/compiler_crashers_2_fixed/Inputs/rdar81590807_2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <Foundation/Foundation.h>

#pragma clang assume_nonnull begin

@interface PFXObject : NSObject {
}
- (void)findAnswerSyncSuccessAsynchronously:
(void (^)(NSString *_Nullable, NSError *_Nullable))handler
__attribute__((swift_name("findAnswerSyncSuccess(completionHandler:)")));
- (void)findAnswerAsyncSuccessAsynchronously:
(void (^)(NSString *_Nullable, NSError *_Nullable))handler
__attribute__((swift_name("findAnswerAsyncSuccess(completionHandler:)")));
- (void)findAnswerSyncFailAsynchronously:
(void (^)(NSString *_Nullable, NSError *_Nullable))handler
__attribute__((swift_name("findAnswerSyncFail(completionHandler:)")));
- (void)findAnswerAsyncFailAsynchronously:
(void (^)(NSString *_Nullable, NSError *_Nullable))handler
__attribute__((swift_name("findAnswerAsyncFail(completionHandler:)")));
- (void)findAnswerIncorrectAsynchronously:
(void (^)(NSString *_Nullable, NSError *_Nullable))handler
__attribute__((swift_name("findAnswerIncorrect(completionHandler:)")));
@end

#pragma clang assume_nonnull end
Loading