Skip to content

Commit 56531cb

Browse files
committed
Merge pull request swiftlang#1 from jrose-apple/import-lightweight-objc-generics
Convert to StdlibUnittest, fix type metadata conventions
2 parents 679d3bf + cbd1c8d commit 56531cb

File tree

7 files changed

+125
-93
lines changed

7 files changed

+125
-93
lines changed

Diff for: lib/IRGen/Fulfillment.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ bool FulfillmentMap::searchBoundGenericTypeMetadata(ModuleDecl &M,
230230
unsigned source,
231231
MetadataPath &&path,
232232
const InterestingKeysCallback &keys) {
233+
if (type->getDecl()->hasClangNode())
234+
return false;
235+
233236
auto params = type->getDecl()->getGenericParams()->getAllArchetypes();
234237
auto substitutions = type->getSubstitutions(&M, nullptr);
235238
assert(params.size() >= substitutions.size() &&

Diff for: lib/IRGen/GenMeta.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -1764,21 +1764,14 @@ llvm::Value *irgen::emitClassHeapMetadataRef(IRGenFunction &IGF, CanType type,
17641764
return classPtr;
17651765
}
17661766

1767-
// ObjC-defined classes will always be top-level non-generic classes.
1768-
1769-
if (auto classType = dyn_cast<ClassType>(type)) {
1770-
auto theClass = classType->getDecl();
1767+
if (ClassDecl *theClass = type->getClassOrBoundGenericClass()) {
17711768
if (!hasKnownSwiftMetadata(IGF.IGM, theClass)) {
17721769
llvm::Value *result =
17731770
emitObjCHeapMetadataRef(IGF, theClass, allowUninitialized);
17741771
if (desiredType == MetadataValueType::TypeMetadata)
17751772
result = IGF.Builder.CreateBitCast(result, IGF.IGM.TypeMetadataPtrTy);
17761773
return result;
17771774
}
1778-
} else {
1779-
auto genericType = cast<BoundGenericClassType>(type);
1780-
assert(hasKnownSwiftMetadata(IGF.IGM, genericType->getDecl()));
1781-
(void) genericType;
17821775
}
17831776

17841777
llvm::Value *result = IGF.emitTypeMetadataRef(type);

Diff for: lib/IRGen/GenProto.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1283,9 +1283,13 @@ bool irgen::hasPolymorphicParameters(CanSILFunctionType ty) {
12831283
case SILFunctionTypeRepresentation::Thick:
12841284
case SILFunctionTypeRepresentation::Thin:
12851285
case SILFunctionTypeRepresentation::Method:
1286-
case SILFunctionTypeRepresentation::ObjCMethod:
12871286
return ty->isPolymorphic();
12881287

1288+
case SILFunctionTypeRepresentation::ObjCMethod:
1289+
// May be polymorphic at the SIL level, but no type metadata is actually
1290+
// passed.
1291+
return false;
1292+
12891293
case SILFunctionTypeRepresentation::WitnessMethod:
12901294
// Always carries polymorphic parameters for the Self type.
12911295
return true;
@@ -1482,8 +1486,6 @@ namespace {
14821486

14831487
private:
14841488
void initGenerics() {
1485-
assert(hasPolymorphicParameters(FnType));
1486-
14871489
// The canonical mangling signature removes dependent types that are
14881490
// equal to concrete types, but isn't necessarily parallel with
14891491
// substitutions.

Diff for: lib/IRGen/IRGenSIL.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -1290,16 +1290,14 @@ static void emitEntryPointArgumentsCOrObjC(IRGenSILFunction &IGF,
12901290

12911291
assert(params.empty() && "didn't claim all parameters!");
12921292

1293-
// Bind polymorphic arguments. This can only be done after binding
1294-
// all the value parameters.
1295-
if (hasPolymorphicParameters(funcTy)) {
1296-
emitPolymorphicParameters(IGF, *IGF.CurSILFn, params,
1297-
nullptr,
1298-
[&](unsigned paramIndex) -> llvm::Value* {
1299-
SILValue parameter = entry->getBBArgs()[paramIndex];
1300-
return IGF.getLoweredSingletonExplosion(parameter);
1301-
});
1302-
}
1293+
// Bind polymorphic arguments. This can only be done after binding
1294+
// all the value parameters, and must be done even for non-polymorphic
1295+
// functions because of imported Objective-C generics.
1296+
emitPolymorphicParameters(IGF, *IGF.CurSILFn, params, nullptr,
1297+
[&](unsigned paramIndex) -> llvm::Value* {
1298+
SILValue parameter = entry->getBBArgs()[paramIndex];
1299+
return IGF.getLoweredSingletonExplosion(parameter);
1300+
});
13031301
}
13041302

13051303
/// Get metadata for the dynamic Self type if we have it.

Diff for: test/Interpreter/Inputs/ObjCClasses/ObjCClasses.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef SWIFT_TEST_OBJC_CLASSES_H
22
#define SWIFT_TEST_OBJC_CLASSES_H
33

4-
#include <Foundation/NSObject.h>
4+
#import <Foundation/NSObject.h>
5+
6+
NS_ASSUME_NONNULL_BEGIN
57

68
/* This class has instance variables which are not apparent in the
79
interface. Subclasses will need to be slid by the ObjC runtime. */
@@ -19,10 +21,12 @@
1921

2022
@interface Container<C> : NSObject
2123
- (id)initWithObject:(C)object NS_DESIGNATED_INITIALIZER;
24+
- (id)init NS_UNAVAILABLE;
25+
2226
@property C object;
2327

2428
- (void)processObjectWithBlock:(void (^)(C))block;
25-
- (void)getObjectWithBlock:(C (^)())block;
29+
- (void)updateObjectWithBlock:(C (^)())block;
2630
@end
2731

2832
@interface Container<D> (Cat1)
@@ -45,7 +49,7 @@
4549
@end
4650

4751
@interface Animal : NSObject
48-
- (void)makeNoise;
52+
@property (readonly) NSString *noise;
4953
@end
5054

5155
@interface Dog : Animal
@@ -54,4 +58,6 @@
5458
@interface AnimalContainer<C: Animal *> : Container<C>
5559
@end
5660

61+
NS_ASSUME_NONNULL_END
62+
5763
#endif

Diff for: test/Interpreter/Inputs/ObjCClasses/ObjCClasses.m

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ - (void)processObjectWithBlock:(void (^)(id))block {
2626
block(self.object);
2727
}
2828

29-
- (void)getObjectWithBlock:(id (^)())block {
29+
- (void)updateObjectWithBlock:(id (^)())block {
3030
self.object = block();
3131
}
3232

@@ -67,14 +67,14 @@ @implementation CopyingContainer
6767
@end
6868

6969
@implementation Animal
70-
- (void)makeNoise {
71-
printf("eep\n");
70+
- (NSString *)noise {
71+
return @"eep";
7272
}
7373
@end
7474

7575
@implementation Dog
76-
- (void)makeNoise {
77-
printf("woof\n");
76+
- (NSString *)noise {
77+
return @"woof";
7878
}
7979
@end
8080

Diff for: test/Interpreter/imported_objc_generics.swift

+94-64
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,115 @@
22
// RUN: mkdir -p %t
33
//
44
// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
5-
// RUN: %target-build-swift -Xfrontend -enable-import-objc-generics -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out
6-
// RUN: %target-run %t/a.out | FileCheck %s
5+
// RUN: %target-build-swift -Xfrontend -enable-import-objc-generics -I %S/Inputs/ObjCClasses/ %t/ObjCClasses.o %s -o %t/a.out
6+
// RUN: %target-run %t/a.out
77

88
// REQUIRES: executable_test
9+
// XFAIL: interpret
910
// REQUIRES: objc_interop
1011

1112
import Foundation
13+
import StdlibUnittest
1214
import ObjCClasses
1315

14-
let cs = Container<NSString>(object: "i-just-met-you")
15-
print(cs)
16-
// CHECK: <Container: {{.*}}>
17-
print(cs.object)
18-
// CHECK: i-just-met-you
19-
20-
cs.processObjectWithBlock { s in print("in block: \(s)!!!") }
21-
// CHECK: in block: i-just-met-you!!!
22-
cs.getObjectWithBlock { () in NSString(string: "this-is-crazy") }
23-
print(cs.object)
24-
// CHECK: this-is-crazy
25-
cs.object = "so-heres-my-number"
26-
print(cs.object)
27-
// CHECK: so-heres-my-number
28-
29-
let cs2 = Container<NSString>(object: "call-me-maybe")
30-
print(cs2.getCat1())
31-
// CHECK: call-me-maybe
32-
cs2.setCat1(":)")
33-
print(cs2.cat1Property)
34-
// CHECK: :)
35-
36-
let scs = SubContainer<NSString>(object: "hey neat")
37-
print(scs.object)
38-
// CHECK: hey neat
39-
40-
let nestedContainer = NestedContainer<NSString>(object: Container<NSString>(object: "cat"))
41-
print(nestedContainer.object.object)
42-
// CHECK: cat
43-
44-
let stringContainer = StringContainer(object: "stringy")
45-
print(stringContainer.object)
46-
// CHECK: stringy
16+
var ImportedObjCGenerics = TestSuite("ImportedObjCGenerics")
17+
18+
ImportedObjCGenerics.test("Creation") {
19+
let cs = Container<NSString>(object: "i-just-met-you")
20+
expectEqual("i-just-met-you", cs.object)
21+
expectTrue(cs.dynamicType === Container<NSString>.self)
22+
expectTrue(cs.dynamicType === Container<AnyObject>.self)
23+
}
24+
25+
ImportedObjCGenerics.test("Blocks") {
26+
let cs = Container<NSString>(object: "and-this-is-crazy")
27+
28+
var fromBlock: NSString = ""
29+
cs.processObjectWithBlock { fromBlock = $0 }
30+
expectEqual("and-this-is-crazy", fromBlock)
31+
32+
cs.updateObjectWithBlock { "but-heres-my-number" }
33+
expectEqual("but-heres-my-number", cs.object)
34+
}
35+
36+
ImportedObjCGenerics.test("Categories") {
37+
let cs = Container<NSString>(cat1: "so-call-me-maybe")
38+
expectEqual("so-call-me-maybe", cs.getCat1())
39+
40+
cs.setCat1("its-hard-to-look-right")
41+
expectEqual("its-hard-to-look-right", cs.cat1Property)
42+
}
43+
44+
ImportedObjCGenerics.test("Subclasses") {
45+
let subContainer = SubContainer<NSString>(object: "at-you-baby")
46+
expectEqual("at-you-baby", subContainer.object)
47+
48+
let nestedContainer = NestedContainer<NSString>(object: Container(object: "but-heres-my-number"))
49+
expectEqual("but-heres-my-number", nestedContainer.object.object)
50+
51+
let stringContainer = StringContainer(object: "so-call-me-maybe")
52+
expectEqual("so-call-me-maybe", stringContainer.object)
53+
}
54+
55+
ImportedObjCGenerics.test("SwiftGenerics") {
56+
func openContainer<T: AnyObject>(x: Container<T>) -> T {
57+
return x.object
58+
}
59+
func openStringContainer<T: Container<NSString>>(x: T) -> NSString {
60+
return x.object
61+
}
62+
func openArbitraryContainer<S: AnyObject, T: Container<S>>(x: T) -> S {
63+
return x.object
64+
}
65+
66+
let scs = SubContainer<NSString>(object: "before-you-came-into-my-life")
67+
expectEqual("before-you-came-into-my-life", openContainer(scs))
68+
expectEqual("before-you-came-into-my-life", openStringContainer(scs))
69+
expectEqual("before-you-came-into-my-life", openArbitraryContainer(scs))
70+
71+
let cs = Container<NSString>(object: "i-missed-you-so-bad")
72+
expectEqual("i-missed-you-so-bad", openContainer(cs))
73+
expectEqual("i-missed-you-so-bad", openStringContainer(cs))
74+
expectEqual("i-missed-you-so-bad", openArbitraryContainer(cs))
75+
76+
let strContainer = SubContainer<NSString>(object: "i-missed-you-so-so-bad")
77+
expectEqual("i-missed-you-so-so-bad", openContainer(strContainer))
78+
expectEqual("i-missed-you-so-so-bad", openStringContainer(strContainer))
79+
expectEqual("i-missed-you-so-so-bad", openArbitraryContainer(strContainer))
80+
81+
let numContainer = Container<NSNumber>(object: NSNumber(integer: 21))
82+
expectEqual(NSNumber(integer: 21), openContainer(numContainer))
83+
expectEqual(NSNumber(integer: 21), openArbitraryContainer(numContainer))
84+
85+
let subNumContainer = SubContainer<NSNumber>(object: NSNumber(integer: 22))
86+
expectEqual(NSNumber(integer: 22), openContainer(subNumContainer))
87+
expectEqual(NSNumber(integer: 22), openArbitraryContainer(subNumContainer))
88+
}
4789

4890
// TODO: resolve crash in IRGen from test case below
4991
/*func makeContainer<T: AnyObject>(x: T) -> Container<T> {*/
5092
/*return Container(object: x)*/
5193
/*}*/
5294

53-
func openContainer<T: AnyObject>(x: Container<T>) -> T {
54-
return x.object
95+
ImportedObjCGenerics.test("SwiftGenerics/Creation") {
96+
// TODO: Test above.
5597
}
56-
print(openContainer(Container<NSString>(object: "some string")))
57-
// CHECK: some string
5898

59-
func openStringContainer<T: Container<NSString>>(x: T) -> NSString {
60-
return x.object
61-
}
62-
print(openStringContainer(Container<NSString>(object: "some string")))
63-
// CHECK: some string
64-
print(openStringContainer(SubContainer<NSString>(object: "some string 2")))
65-
// CHECK: some string 2
66-
print(openStringContainer(StringContainer(object: "some string 3")))
67-
// CHECK: some string 3
68-
69-
func openArbitraryContainer<S: AnyObject, T: Container<S>>(x: T) -> S {
70-
return x.object
71-
}
72-
print(openArbitraryContainer(Container<NSString>(object: "some string 4")))
73-
// CHECK: some string 4
74-
print(openArbitraryContainer(Container<NSNumber>(object: NSNumber(integer: 5))) as NSNumber)
75-
// CHECK: 5
76-
77-
let _ = CopyingContainer<NSString>()
78-
func copyContainerContents<T: NSCopying>(x: CopyingContainer<T>) -> T {
79-
return x.object.copyWithZone(nil) as! T
99+
ImportedObjCGenerics.test("ProtocolConstraints") {
100+
func copyContainerContents<T: NSCopying>(x: CopyingContainer<T>) -> T {
101+
return x.object.copyWithZone(nil) as! T
102+
}
103+
104+
let cs = CopyingContainer<NSString>(object: "Happy 2012")
105+
expectEqual("Happy 2012", copyContainerContents(cs))
80106
}
81107

82-
func makeContainedAnimalMakeNoise<T: Animal>(x: AnimalContainer<T>) {
83-
x.object.makeNoise()
108+
ImportedObjCGenerics.test("ClassConstraints") {
109+
func makeContainedAnimalMakeNoise<T>(x: AnimalContainer<T>) -> NSString {
110+
return x.object.noise
111+
}
112+
let petCarrier = AnimalContainer(object: Dog())
113+
expectEqual("woof", makeContainedAnimalMakeNoise(petCarrier))
84114
}
85-
makeContainedAnimalMakeNoise(AnimalContainer(object: Dog()))
86-
// CHECK: woof
115+
116+
runAllTests()

0 commit comments

Comments
 (0)