Skip to content

Commit 409132c

Browse files
committed
[Clang importer] swift_newtype'd types are bridged when their underlying types are.
A swift_wrapper/swift_newtype'd type can wrap a bridged type. In such cases, we need to report both the unbridged type (which is the unbridged underlying type) and the bridged type (which is the importer-created wrapper type). This fixes a problem where Objective-C generic specializations would use the wrapper types on type parameters with "AnyObject" constraints, which... doesn't work. Fixes rdar://problem/26340353.
1 parent e41a321 commit 409132c

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ namespace {
6363
/// The source type is 'Boolean'.
6464
Boolean,
6565

66-
/// The source type an Objective-C class type bridged to a Swift
66+
/// The source type is an Objective-C class type bridged to a Swift
6767
/// type.
6868
ObjCBridged,
6969

@@ -565,6 +565,15 @@ namespace {
565565
hint = ImportHint::SwiftNewtypeFromCFPointer;
566566
else
567567
hint = ImportHint::SwiftNewtype;
568+
569+
// If the underlying type was bridged, the wrapper type is
570+
// only useful in bridged cases.
571+
auto underlying = Visit(type->getDecl()->getUnderlyingType());
572+
if (underlying.Hint == ImportHint::ObjCBridged) {
573+
return { underlying.AbstractType,
574+
ImportHint(ImportHint::ObjCBridged, mappedType) };
575+
}
576+
568577
// For certain special typedefs, we don't want to use the imported type.
569578
} else if (auto specialKind = Impl.getSpecialTypedefKind(type->getDecl())) {
570579
switch (specialKind.getValue()) {
@@ -1187,7 +1196,7 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
11871196
}
11881197

11891198
// For types we import as new types in Swift, if the use is CF un-audited,
1190-
// then we have to for it to be unmanaged
1199+
// then we have to force it to be unmanaged
11911200
if (hint == ImportHint::SwiftNewtypeFromCFPointer &&
11921201
!isCFAudited(importKind)) {
11931202
auto underlyingType = importedType->getSwiftNewtypeUnderlyingType();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@import Foundation;
2+
3+
typedef NSString *_Nonnull SNTClosedEnum __attribute((swift_newtype(enum)))
4+
__attribute((swift_name("ClosedEnum")));
5+
6+
extern const SNTClosedEnum SNTFirstClosedEntryEnum;
7+
extern const SNTClosedEnum SNTSecondEntry;
8+
extern const SNTClosedEnum SNTClosedEnumThirdEntry;
9+
10+
@interface GenericClassA<T> : NSObject
11+
@end
12+
13+
@interface UsesGenericClassA : NSObject
14+
-(void)takeEnumValues:(nonnull GenericClassA<SNTClosedEnum> *)values;
15+
-(void)takeEnumValuesArray:(nonnull NSArray<SNTClosedEnum> *)values;
16+
@end

test/IDE/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ module Newtype {
1616
header "Newtype.h"
1717
}
1818

19+
module NewtypeObjC {
20+
header "NewtypeObjC.h"
21+
export *
22+
}
23+
1924
module ImportAsMember {
2025
export *
2126

test/IDE/newtype.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func tests() {
8585
fooErr.process()
8686
Food().process() // expected-error{{value of type 'Food' has no member 'process'}}
8787

88-
let thirdEnum = ClosedEnum.thirdEntry!
88+
let thirdEnum = ClosedEnum.thirdEntry
8989
thirdEnum.process()
9090
// expected-error@-1{{value of type 'ClosedEnum' has no member 'process'}}
9191

test/IDE/newtype_objc.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: %build-clang-importer-objc-overlays
4+
5+
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk-nosource) -I %t -I %S/Inputs/custom-modules -print-module -source-filename %s -module-to-print=NewtypeObjC -enable-swift-newtype > %t.printed.NewtypeObjC.txt
6+
// RUN: FileCheck %s -check-prefix=PRINT -strict-whitespace < %t.printed.NewtypeObjC.txt
7+
// RUN: %target-parse-verify-swift -sdk %clang-importer-sdk -I %S/Inputs/custom-modules -I %t -enable-swift-newtype %s
8+
9+
// REQUIRES: objc_interop
10+
11+
// PRINT: class UsesGenericClassA : NSObject {
12+
// PRINT: func takeEnumValues(_ values: GenericClassA<NSString>)
13+
// PRINT: func takeEnumValuesArray(_ values: [ClosedEnum])
14+
// PRINT: }
15+
16+
import NewtypeObjC
17+
18+
func useSpecializationOverNewtypes(a: UsesGenericClassA) {
19+
let gca = GenericClassA<NSString>()
20+
a.takeEnumValues(gca)
21+
}

0 commit comments

Comments
 (0)