Skip to content

Don't flatten input types in ObjC representation check #17123

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 1 commit into from
Jun 13, 2018
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
45 changes: 28 additions & 17 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1951,30 +1951,41 @@ getForeignRepresentable(Type type, ForeignLanguage language,
break;
}

auto success = [](bool anyStaticBridged,
bool anyBridged,
bool isBlock) -> std::pair<ForeignRepresentableKind,
ProtocolConformance *> {
// We have something representable; check how it is representable.
return { anyStaticBridged ? ForeignRepresentableKind::StaticBridged
: anyBridged ? ForeignRepresentableKind::Bridged
: isBlock ? ForeignRepresentableKind::Object
: ForeignRepresentableKind::Trivial,
nullptr };
};

// HACK: In Swift 3 mode, we accepted (Void) -> Void for () -> Void
if (dc->getASTContext().isSwiftVersion3()
&& functionType->getParams().size() == 1
&& functionType->getParams()[0].getLabel().empty()
&& functionType->getParams()[0].getType()->isVoid()
&& functionType->getResult()->isVoid()) {
return success(anyStaticBridged, anyBridged, isBlock);
}

// Look at the result type.
Type resultType = functionType->getResult();
if (!resultType->isVoid() && recurse(resultType))
return failure();

// Look at the input types.
Type inputType = functionType->getInput();
if (auto inputTuple = inputType->getAs<TupleType>()) {
for (const auto &elt : inputTuple->getElements()) {
if (elt.isVararg())
return failure();
if (recurse(elt.getType()))
return failure();
}
} else if (recurse(inputType)) {
return failure();
// Look at the input params.
for (const auto &param : functionType->getParams()) {
if (param.isVariadic())
return failure();
if (recurse(param.getType()))
return failure();
}

// We have something representable; check how it is representable.
return { anyStaticBridged ? ForeignRepresentableKind::StaticBridged
: anyBridged ? ForeignRepresentableKind::Bridged
: isBlock ? ForeignRepresentableKind::Object
: ForeignRepresentableKind::Trivial,
nullptr };
return success(anyStaticBridged, anyBridged, isBlock);
}

// Give special dispensation to builtin types for testing purposes.
Expand Down
11 changes: 11 additions & 0 deletions test/ClangImporter/objc_parse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,17 @@ class NewtypeUser {
@objc func intNewtypeDictionary(a: [MyInt: NSObject]) {} // expected-error {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
@objc func cfNewtype(a: CFNewType) {}
@objc func cfNewtypeArray(a: [CFNewType]) {} // expected-error {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}

typealias MyTuple = (Int, AnyObject?)
typealias MyNamedTuple = (a: Int, b: AnyObject?)

@objc func blockWithTypealias(_ input: @escaping (MyTuple) -> MyInt) {}
// expected-error@-1{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
// expected-note@-2{{function types cannot be represented in Objective-C}}

@objc func blockWithTypealiasWithNames(_ input: (MyNamedTuple) -> MyInt) {}
// expected-error@-1{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
// expected-note@-2{{function types cannot be represented in Objective-C}}
}

func testTypeAndValue() {
Expand Down
8 changes: 0 additions & 8 deletions test/PrintAsObjC/blocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

import ObjectiveC

typealias MyTuple = (Int, AnyObject?)
typealias MyNamedTuple = (a: Int, b: AnyObject?)
typealias MyInt = Int
typealias MyBlockWithEscapingParam = (@escaping () -> ()) -> Int
typealias MyBlockWithNoescapeParam = (() -> ()) -> Int
Expand Down Expand Up @@ -60,9 +58,6 @@ typealias MyBlockWithNoescapeParam = (() -> ()) -> Int
@objc func returnsBlockWithTwoInputs() -> ((NSObject, NSObject) -> ())? {
return nil
}

// CHECK-NEXT: - (void)blockWithTypealias:(NSInteger (^ _Nonnull)(NSInteger, id _Nullable))input;
@objc func blockWithTypealias(_ input: @escaping (MyTuple) -> MyInt) {}

// CHECK-NEXT: - (void)blockWithSimpleTypealias:(NSInteger (^ _Nonnull)(NSInteger))input;
@objc func blockWithSimpleTypealias(_ input: @escaping (MyInt) -> MyInt) {}
Expand All @@ -78,9 +73,6 @@ typealias MyBlockWithNoescapeParam = (() -> ()) -> Int
return nil
}

// CHECK-NEXT: - (void)blockWithTypealiasWithNames:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger a, id _Nullable b))input;
@objc func blockWithTypealiasWithNames(_ input: (MyNamedTuple) -> MyInt) {}

// CHECK-NEXT: - (void)blockWithKeyword:(SWIFT_NOESCAPE NSInteger (^ _Nonnull)(NSInteger))_Nullable_;
@objc func blockWithKeyword(_ _Nullable: (_ `class`: Int) -> Int) {}

Expand Down